summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/mozilla')
-rw-r--r--testing/web-platform/mozilla/README4
-rw-r--r--testing/web-platform/mozilla/meta/__dir__.ini4
-rw-r--r--testing/web-platform/mozilla/meta/audio-output/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/baselinecoverage/wpt_baselinecoverage.html.ini3
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html.ini14
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html.ini16
-rw-r--r--testing/web-platform/mozilla/meta/css/css-contain/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini24
-rw-r--r--testing/web-platform/mozilla/meta/css/cssom/window_size_rounding.html.ini5
-rw-r--r--testing/web-platform/mozilla/meta/css/iframe-os-text-scale-print.sub.html.ini5
-rw-r--r--testing/web-platform/mozilla/meta/css/mediaqueries/mq-gamut-resist-fingerprinting.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/dom/delayed_window_print.html.ini6
-rw-r--r--testing/web-platform/mozilla/meta/dom/range-in-two-selections.html.ini1
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/__dir__.ini5
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-1.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-2.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-3.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-4.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-indexeddb.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-webaudio.window.js.ini5
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-webrtc.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/dom/throttling/throttling-ws.window.js.ini4
-rw-r--r--testing/web-platform/mozilla/meta/editor/delete-space-after-double-click-selection.html.ini6
-rw-r--r--testing/web-platform/mozilla/meta/fetch/api/redirect/redirect-referrer.https.html.ini3
-rw-r--r--testing/web-platform/mozilla/meta/fetch/orb/__dir__.ini3
-rw-r--r--testing/web-platform/mozilla/meta/focus/Selection_extend.html.ini20
-rw-r--r--testing/web-platform/mozilla/meta/focus/focus-next-tick-before-iframe-loaded-different-site.html.ini4
-rw-r--r--testing/web-platform/mozilla/meta/html/semantics/scripting-1/the-script-element/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini3
-rw-r--r--testing/web-platform/mozilla/meta/infrastructure/prefs/prefs-1.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html.ini3
-rw-r--r--testing/web-platform/mozilla/meta/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini6
-rw-r--r--testing/web-platform/mozilla/meta/mediacapture-streams/enumerateDevices-in-background.https.html.ini3
-rw-r--r--testing/web-platform/mozilla/meta/screen-capture/getdisplaymedia-user-activation-consumed.https.html.ini5
-rw-r--r--testing/web-platform/mozilla/meta/wasm/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/bidi/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/reference_context.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/type_hint.py.ini9
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/bidi/interface/interface.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/bidi/websocket_upgrade.py.ini3
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/cdp/debugger_address.py.ini11
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/cdp/port_file.py.ini3
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/execute_async_script/execute_async.py.ini16
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/get_window_handles/chrome.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/new_session/__dir__.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/new_session/binary.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/new_session/profile_root.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/protocol/marionette_port.py.ini8
-rw-r--r--testing/web-platform/mozilla/meta/webdriver/classic/send_alert_text.py.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/__dir__.ini5
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/1/cts.https.html.ini823
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/10/cts.https.html.ini456
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/11/cts.https.html.ini2531
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/12/cts.https.html.ini1125
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/13/cts.https.html.ini15741
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/14/cts.https.html.ini2076
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/15/cts.https.html.ini273
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/16/cts.https.html.ini6474
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/17/cts.https.html.ini405
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/18/cts.https.html.ini945
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/19/cts.https.html.ini297
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/2/cts.https.html.ini5925
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/20/cts.https.html.ini7779
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/21/cts.https.html.ini6492
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/22/cts.https.html.ini279
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/23/cts.https.html.ini374
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/24/cts.https.html.ini5687
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/25/cts.https.html.ini991
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/26/cts.https.html.ini2325
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/27/cts.https.html.ini5645
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/28/cts.https.html.ini824
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/29/cts.https.html.ini592
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/3/cts.https.html.ini1044
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/30/cts.https.html.ini651
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/31/cts.https.html.ini1224
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/32/cts.https.html.ini1203
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/33/cts.https.html.ini459
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/34/cts.https.html.ini1104
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/35/cts.https.html.ini780
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/36/cts.https.html.ini1116
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/37/cts.https.html.ini1056
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/38/cts.https.html.ini1068
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/39/cts.https.html.ini528
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/4/cts.https.html.ini1488
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/40/cts.https.html.ini1224
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/41/cts.https.html.ini1164
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/42/cts.https.html.ini849
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/43/cts.https.html.ini189
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/44/cts.https.html.ini426
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/45/cts.https.html.ini738
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/46/cts.https.html.ini8169
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/47/cts.https.html.ini1539
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/48/cts.https.html.ini123
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/49/cts.https.html.ini9696
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/5/cts.https.html.ini753
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/50/cts.https.html.ini1945
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/51/cts.https.html.ini4102
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/6/cts.https.html.ini6297
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/7/cts.https.html.ini1710
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/8/cts.https.html.ini1137
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/chunked/9/cts.https.html.ini588
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/__dir__.ini4
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/resize_observer.https.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/webtransport/__dir__.ini4
-rw-r--r--testing/web-platform/mozilla/meta/workers/__dir__.ini1
-rw-r--r--testing/web-platform/mozilla/meta/workers/bug1674278-crash.html.ini2
-rw-r--r--testing/web-platform/mozilla/meta/workers/modules/dedicated-worker-import-csp.html.ini7
-rw-r--r--testing/web-platform/mozilla/meta/workers/modules/shared-worker-import-csp.html.ini14
-rw-r--r--testing/web-platform/mozilla/tests/audio-output/selectAudioOutput-user-activation-consumed.https.html30
-rw-r--r--testing/web-platform/mozilla/tests/baselinecoverage/wpt_baselinecoverage.html22
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html118
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html119
-rw-r--r--testing/web-platform/mozilla/tests/content-security-policy/generic/test-case.sub.js98
-rw-r--r--testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-document-reflow-count.html44
-rw-r--r--testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-reflow-count.html120
-rw-r--r--testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html115
-rw-r--r--testing/web-platform/mozilla/tests/css/cssom/media-print-change-print-ref.html2
-rw-r--r--testing/web-platform/mozilla/tests/css/cssom/media-print-change-print.html8
-rw-r--r--testing/web-platform/mozilla/tests/css/cssom/window_size_rounding.html35
-rw-r--r--testing/web-platform/mozilla/tests/css/file-selector-button-margin-notref.html2
-rw-r--r--testing/web-platform/mozilla/tests/css/file-selector-button-margin.html10
-rw-r--r--testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print-ref.html5
-rw-r--r--testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print.sub.html6
-rw-r--r--testing/web-platform/mozilla/tests/css/mediaqueries/mq-gamut-resist-fingerprinting.html40
-rw-r--r--testing/web-platform/mozilla/tests/css/quirks-invalidation-standard-sheet.html14
-rw-r--r--testing/web-platform/mozilla/tests/css/reference/ref-filled-green-100px-square.xht19
-rw-r--r--testing/web-platform/mozilla/tests/css/resources/iframe-os-text-scale-inner.html9
-rw-r--r--testing/web-platform/mozilla/tests/dom/classList.html526
-rw-r--r--testing/web-platform/mozilla/tests/dom/delayed_window_print.html39
-rw-r--r--testing/web-platform/mozilla/tests/dom/dispatch_select_event.html35
-rw-r--r--testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html63
-rw-r--r--testing/web-platform/mozilla/tests/dom/range-in-two-selections.html34
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/test.html5
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js136
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js3
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js10
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js37
-rw-r--r--testing/web-platform/mozilla/tests/editor/delete-space-after-double-click-selection.html278
-rw-r--r--testing/web-platform/mozilla/tests/editor/input-setRangeText-during-noframe-crash.html18
-rw-r--r--testing/web-platform/mozilla/tests/editor/white-space-handling-in-mail-editor.html371
-rw-r--r--testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer-mixed-content.js51
-rw-r--r--testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer.https.html18
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/content-range.sub.window.js19
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/img-mime-types-coverage.tentative.sub.html43
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/known-mime-type.sub.window.js48
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/nosniff.sub.window.js44
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/resources/utils.js21
-rw-r--r--testing/web-platform/mozilla/tests/fetch/orb/tentative/status.sub.window.js30
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_collapse.html207
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_selectNode.html267
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_setEnd.html364
-rw-r--r--testing/web-platform/mozilla/tests/focus/Range_setStart.html353
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange.html1242
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html63
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html67
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html9
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapse.html148
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html134
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html142
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_extend.html189
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html112
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_removeRange.html112
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html254
-rw-r--r--testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html926
-rw-r--r--testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html19
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html16
-rw-r--r--testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html75
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html50
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html17
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html50
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html42
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html31
-rw-r--r--testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html42
-rw-r--r--testing/web-platform/mozilla/tests/html/browsers/browsing-the-web/read-media/sandboxed-video.html24
-rw-r--r--testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-01.html59
-rw-r--r--testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-02.html41
-rw-r--r--testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-03.html45
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/form-submission-0/non-usv-filenames.window.js95
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/input-radio-key-navigation.html61
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/textfieldselection/selection-value-interactions.html217
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01-notref.html3
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01.html13
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02-notref.html9
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02.html14
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03-ref.html7
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03.html15
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04-ref.html7
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04.html14
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/forms/time-enter-keypress.html48
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-circular.html25
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-error.html25
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module.html25
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-circular.html28
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-error.html25
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module.html21
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/circular-module-import-with-syntax-error.html26
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/create-module-script.html25
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/mixed-content-import.https.html27
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/module-error-reporting.html89
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/reload-failed-module-script.html41
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module.js11
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_circular.js5
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_error.js5
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module.js14
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_circular.js3
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_error.js4
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module.js12
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_1.js3
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_2.js5
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_3.js8
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_failure.js6
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/bad_local_export.js3
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error1.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error2.js1
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error3.js1
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/evaluation-order-setup.mjs19
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/import_resolve_failure.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/indirect_export_resolve_failure.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_import.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_indirect_export.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import.js1
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import2.js1
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module.js2
-rw-r--r--testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module_eval_error.js3
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/README.md7
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-after-template.html10
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-ncr.html10
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript.html10
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/in-svg-in-cdata-after-gt.html10
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-after-template-ref.html9
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ncr-ref.html9
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ref.html9
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/charset/references/in-svg-in-cdata-after-gt-ref.html10
-rw-r--r--testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html62
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/LICENSE359
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/README.txt14
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/baskar-jagran.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/elango.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/htchanakya.html12
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/shreetam.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/tab.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/tam.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/tboomi.html10
-rw-r--r--testing/web-platform/mozilla/tests/indic-detection/tscii.html10
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-0.html12
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-1.html11
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-2.html10
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-false.html5
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-true.html5
-rw-r--r--testing/web-platform/mozilla/tests/infrastructure/specialPowers/specialpowers.html7
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font-ref.html15
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html20
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur-ref.html79
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur.html85
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic-ref.html137
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic.html143
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-ref.html149
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif-ref.html147
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif.html153
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script-ref.html79
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script.html85
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold.html155
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity-ref.html163
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity.html168
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight-ref.html25
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight.html30
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-ref.html114
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck.html120
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur-ref.html79
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur.html85
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial-ref.html47
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial.html53
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic-ref.html139
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic.html145
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped-ref.html54
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped.html60
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace-ref.html89
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace.html95
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic-ref.html137
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic.html143
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic-ref.html79
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic.html85
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-ref.html89
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif.html95
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script-ref.html79
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script.html85
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched-ref.html50
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched.html56
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed-ref.html42
-rw-r--r--testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed.html48
-rw-r--r--testing/web-platform/mozilla/tests/media/2x2-green.ogvbin0 -> 7660 bytes
-rw-r--r--testing/web-platform/mozilla/tests/mediacapture-streams/MediaDevices-enumerateDevices.https.html110
-rw-r--r--testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-in-background.https.html67
-rw-r--r--testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-without-focus.https.html58
-rw-r--r--testing/web-platform/mozilla/tests/mediacapture-streams/permission-helper.js24
-rw-r--r--testing/web-platform/mozilla/tests/placeholder6
-rw-r--r--testing/web-platform/mozilla/tests/screen-capture/getdisplaymedia-user-activation-consumed.https.html30
-rw-r--r--testing/web-platform/mozilla/tests/selection/Selection-addRange-same-instance.html56
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html34
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html42
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/blank.html2
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html15
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js26
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html24
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html22
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/empty.js0
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py14
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/green.pngbin0 -> 87 bytes
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js14
-rw-r--r--testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html63
-rw-r--r--testing/web-platform/mozilla/tests/svg/smil-sampling.html44
-rw-r--r--testing/web-platform/mozilla/tests/web-animations/web-animations-print-ref.html4
-rw-r--r--testing/web-platform/mozilla/tests/web-animations/web-animations-print.html20
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py20
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py72
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py31
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py48
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py8
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py26
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py69
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py156
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/cdp/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/cdp/debugger_address.py45
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/cdp/port_file.py30
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/scroll_into_view.py50
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/send_keys.py24
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/execute_async.py59
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/chrome.py25
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/chrome.py43
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/bidi_disabled.py33
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/binary.py33
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/conftest.py58
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/create.py11
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/invalid.py53
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/new_session/profile_root.py38
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/protocol/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_hosts.py53
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_origins.py56
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/protocol/marionette_port.py41
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/protocol/request.py72
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/send_alert_text.py22
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/__init__.py12
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/iframe.py47
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/screenshot.py51
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/conftest.py15
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/support/__init__.py0
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/support/context.py20
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/support/fixtures.py256
-rw-r--r--testing/web-platform/mozilla/tests/webdriver/support/network.py78
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/1/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/10/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/11/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/12/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/13/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/14/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/15/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/16/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/17/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/18/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/19/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/2/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/20/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/21/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/22/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/23/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/24/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/25/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/26/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/27/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/28/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/29/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/3/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/30/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/31/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/32/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/33/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/34/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/35/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/36/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/37/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/38/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/39/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/4/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/40/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/41/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/42/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/43/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/44/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/45/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/46/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/47/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/48/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/49/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/5/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/50/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/51/cts.https.html58
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/6/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/7/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/8/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/chunked/9/cts.https.html59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js89
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js310
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js213
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js111
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js10
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js3
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js96
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js45
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js31
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js4
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js159
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js125
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js95
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js84
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js156
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js263
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js45
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js4
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js83
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js647
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js4
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js576
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/util.js11
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/version.js3
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js18
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js37
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js32
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js37
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js73
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/colors.js128
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js40
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js75
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js150
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js8
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/types.js60
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/util.js304
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js25
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js4
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js1229
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js.map1
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/README.md2
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt2020.vp9.webmbin0 -> 4057 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt601.vp9.webmbin0 -> 4015 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt709.vp9.webmbin0 -> 4075 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.mp4bin0 -> 92225 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.theora.ogvbin0 -> 10292 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/red-green.webmvp8.webmbin0 -> 10979 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/resources/webgpu.pngbin0 -> 33475 bytes
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapter.spec.js122
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapterInfo.spec.js55
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js274
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map.spec.js491
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_ArrayBuffer.spec.js90
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js80
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js121
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/mapping_test.js35
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/threading.spec.js30
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js104
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/clearBuffer.spec.js55
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyBufferToBuffer.spec.js110
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js1588
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js1910
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/programmable_state_test.js144
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/state_tracking.spec.js319
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/dynamic_state.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/state_tracking.spec.js636
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute/basic.spec.js166
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/entry_point_name.spec.js13
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/overrides.spec.js505
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/device/lost.spec.js93
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/labels.spec.js13
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.js871
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.js354
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.js257
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/operation_context_helper.js317
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/same_subresource.spec.js709
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/texture_sync_test.js110
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/onSubmittedWorkDone.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/pipeline/default_layout.spec.js28
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/queue/writeBuffer.spec.js233
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js138
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/clear_value.spec.js191
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/resolve.spec.js206
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js355
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeop2.spec.js84
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/alpha_to_coverage.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/culling_tests.spec.js186
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/overrides.spec.js424
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.js462
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/primitive_topology.spec.js482
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js501
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/vertex_only_render_pipeline.spec.js30
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/basic.spec.js357
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js878
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js546
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js327
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js524
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/draw.spec.js745
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/indirect_draw.spec.js258
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/robust_access_index.spec.js9
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/stencil.spec.js575
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/buffer.spec.js886
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js56
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js181
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js152
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js614
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/anisotropy.spec.js326
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/filter_mode.spec.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/lod_clamp.spec.js13
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js198
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js363
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/read.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js55
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/uncapturederror.spec.js35
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/correctness.spec.js1067
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/index_format.spec.js573
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/create.spec.js122
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/destroy.spec.js102
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js1130
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/threading.spec.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js77
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/texture_formats.spec.js446
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js667
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js1135
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js456
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js157
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createSampler.spec.js56
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js877
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js333
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/debugMarker.spec.js99
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginComputePass.spec.js194
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginRenderPass.spec.js213
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/clearBuffer.spec.js242
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/compute_pass.spec.js251
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.js320
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js873
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/debug.spec.js65
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/index_access.spec.js163
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/draw.spec.js827
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/dynamic_state.spec.js296
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.js203
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/render.js30
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.js123
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.js142
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.js185
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render_pass.spec.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/setBindGroup.spec.js436
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js229
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js572
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_state.spec.js205
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js757
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/begin_end.spec.js163
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/common.js30
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js158
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/pipeline_statistics.spec.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.js183
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js259
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js285
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/getBindGroupLayout.spec.js202
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_related.spec.js230
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_texture_copies.spec.js441
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js216
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/layout_related.spec.js480
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js541
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/create.spec.js35
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/destroy.spec.js16
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/buffer_mapped.spec.js266
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js886
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js64
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/submit.spec.js48
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeBuffer.spec.js189
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeTexture.spec.js111
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js631
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js1106
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/resolve.spec.js193
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/storeOp.spec.js76
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js62
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js205
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js385
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js320
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js90
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/multisample_state.spec.js84
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/overrides.spec.js502
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/primitive_state.spec.js43
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/shader_module.spec.js113
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/vertex_state.spec.js639
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_encoder.spec.js879
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_misc.spec.js404
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js1338
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js573
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js403
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js118
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/overrides.spec.js97
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js957
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/destroy.spec.js117
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/rg11b10ufloat_renderable.spec.js109
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js422
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js1808
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js62
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/examples.spec.js275
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js941
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constants/flags.spec.js80
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.html.js52
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html11
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html11
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/idl/idl_test.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js2829
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/evaluation_order.spec.js485
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js9
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js224
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js136
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_arithmetic.spec.js190
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_logical.spec.js251
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js149
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js202
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js156
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js56
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js60
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js93
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js93
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/arrayLength.spec.js17
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js56
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js71
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js67
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAdd.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAnd.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicCompareExchangeWeak.spec.js48
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicExchange.spec.js32
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicLoad.spec.js33
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMax.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMin.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicOr.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicStore.spec.js32
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicSub.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicXor.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js6
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js68
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js160
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js64
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js247
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js246
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js247
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js67
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js33
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js172
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js160
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js338
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js195
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js344
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js247
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js67
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js69
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js81
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidth.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthCoarse.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthFine.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js387
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js90
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js107
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js66
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js66
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js109
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js108
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js88
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js357
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js89
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js89
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js53
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js53
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js61
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js71
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js49
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js141
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js195
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js811
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js227
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js48
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js63
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js65
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js80
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/storageBarrier.spec.js39
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js48
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js161
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGather.spec.js275
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.js135
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureLoad.spec.js183
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLayers.spec.js99
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLevels.spec.js66
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumSamples.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js278
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js176
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js150
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompareLevel.spec.js154
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleGrad.spec.js139
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleLevel.spec.js295
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureStore.spec.js123
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js49
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js41
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js41
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js41
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js41
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js41
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/utils.js46
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupBarrier.spec.js39
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js144
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js988
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js32
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js40
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js36
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js6
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/atomicity.spec.js103
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js220
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/coherence.spec.js528
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js962
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/weak.spec.js447
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/padding.spec.js425
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js472
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js553
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js294
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/shared_structs.spec.js356
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js434
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js193
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/align.spec.js182
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/blankspace.spec.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/builtin.spec.js39
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/comments.spec.js76
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/identifiers.spec.js280
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/literal.spec.js298
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js270
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/source.spec.js30
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/static_assert.spec.js38
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/var_and_let.spec.js73
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/bindings.spec.js114
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/util.js88
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js277
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/entry_point.spec.js138
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/interpolate.spec.js145
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/invariant.spec.js84
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js260
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/util.js68
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_validation_test.js77
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/static_assert/static_assert.spec.js71
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/shader/values.js94
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/buffer.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js207
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js241
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/command_buffer_maker.js61
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js257
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js591
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js1049
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/copy_to_texture.js176
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/create_elements.js69
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js361
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/f32_interval.js1931
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js949
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/memory.js26
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js49
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js194
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture.js59
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js199
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/data_generation.js84
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/layout.js302
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/subresource.js54
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js852
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js332
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js122
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js303
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.spec.js162
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/util/unions.js42
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js425
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/context_creation.spec.js48
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js263
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js464
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/ImageBitmap.spec.js558
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js679
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js16
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js426
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.html.js35
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html12
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace.html.js93
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html23
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex.html.js768
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha.html.js175
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html21
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.html.js80
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/create-pattern-data-url.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/gpu_ref_test.js23
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html22
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html17
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html.js50
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html26
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html26
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html26
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html25
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html90
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.html.js147
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html24
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js170
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js80
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js36
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js16
-rw-r--r--testing/web-platform/mozilla/tests/websockets/bug1793935.any.js23
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/closed.tentative.https.html119
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/connected.tentative.https.html116
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/failed.tentative.https.html120
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/helpers.js17
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/ports.sub.js12
-rw-r--r--testing/web-platform/mozilla/tests/webtransport/bfcache/worker.js50
-rw-r--r--testing/web-platform/mozilla/tests/workers/2-mib-file.py7
-rw-r--r--testing/web-platform/mozilla/tests/workers/bug1674278-crash.html6
-rw-r--r--testing/web-platform/mozilla/tests/workers/bug1674278.js6
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html115
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js17
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html19
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html19
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js20
-rw-r--r--testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html123
-rw-r--r--testing/web-platform/mozilla/tests/workers/resources/worker.js129
-rw-r--r--testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html52
-rw-r--r--testing/web-platform/mozilla/tests/xml/parsedepth.html62
977 files changed, 238458 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/README b/testing/web-platform/mozilla/README
new file mode 100644
index 0000000000..a586769844
--- /dev/null
+++ b/testing/web-platform/mozilla/README
@@ -0,0 +1,4 @@
+This directory is intended for web-platform-tests that currently
+cannot be upstreamed for some reason (e.g. because they depend on
+gecko-specific APIs). When run they are mounted on the server under
+/_mozilla/. \ No newline at end of file
diff --git a/testing/web-platform/mozilla/meta/__dir__.ini b/testing/web-platform/mozilla/meta/__dir__.ini
new file mode 100644
index 0000000000..48ebb02088
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/__dir__.ini
@@ -0,0 +1,4 @@
+leak-threshold:
+ if os == "mac": [tab:10000, gmplugin:20000, default:2100, rdd:400]
+ [tab:10000, gmplugin:20000, default:16000]
+
diff --git a/testing/web-platform/mozilla/meta/audio-output/__dir__.ini b/testing/web-platform/mozilla/meta/audio-output/__dir__.ini
new file mode 100644
index 0000000000..59af59bd2a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/audio-output/__dir__.ini
@@ -0,0 +1 @@
+prefs: [media.setsinkid.enabled:true]
diff --git a/testing/web-platform/mozilla/meta/baselinecoverage/wpt_baselinecoverage.html.ini b/testing/web-platform/mozilla/meta/baselinecoverage/wpt_baselinecoverage.html.ini
new file mode 100644
index 0000000000..786eb0d391
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/baselinecoverage/wpt_baselinecoverage.html.ini
@@ -0,0 +1,3 @@
+[wpt_baselinecoverage.html]
+ disabled:
+ if not ccov: Code-Coverage-Test \ No newline at end of file
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html.ini
new file mode 100644
index 0000000000..445c8abd0a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.http.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html.ini
new file mode 100644
index 0000000000..51a152396b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.https.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html.ini
new file mode 100644
index 0000000000..6e73b074f5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html.ini
@@ -0,0 +1,16 @@
+[worker-import.http.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html.ini
new file mode 100644
index 0000000000..0d52b9236d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html.ini
@@ -0,0 +1,16 @@
+[worker-import.https.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html.ini
new file mode 100644
index 0000000000..445c8abd0a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.http.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html.ini
new file mode 100644
index 0000000000..51a152396b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.https.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html.ini
new file mode 100644
index 0000000000..6e73b074f5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html.ini
@@ -0,0 +1,16 @@
+[worker-import.http.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html.ini
new file mode 100644
index 0000000000..0d52b9236d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html.ini
@@ -0,0 +1,16 @@
+[worker-import.https.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini
new file mode 100644
index 0000000000..445c8abd0a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.http.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html.ini
new file mode 100644
index 0000000000..51a152396b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.https.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html.ini
new file mode 100644
index 0000000000..6e73b074f5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html.ini
@@ -0,0 +1,16 @@
+[worker-import.http.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html.ini
new file mode 100644
index 0000000000..0d52b9236d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html.ini
@@ -0,0 +1,16 @@
+[worker-import.https.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html.ini
new file mode 100644
index 0000000000..445c8abd0a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.http.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html.ini
new file mode 100644
index 0000000000..51a152396b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html.ini
@@ -0,0 +1,14 @@
+[sharedworker-import.https.html]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html.ini
new file mode 100644
index 0000000000..6e73b074f5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html.ini
@@ -0,0 +1,16 @@
+[worker-import.http.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html.ini b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html.ini
new file mode 100644
index 0000000000..0d52b9236d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html.ini
@@ -0,0 +1,16 @@
+[worker-import.https.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
+
+ [Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context.: securitypolicyviolation]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/css/css-contain/__dir__.ini b/testing/web-platform/mozilla/meta/css/css-contain/__dir__.ini
new file mode 100644
index 0000000000..e977af25bc
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/css/css-contain/__dir__.ini
@@ -0,0 +1 @@
+prefs: [layout.css.content-visibility.enabled:true]
diff --git a/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini b/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini
new file mode 100644
index 0000000000..3489dc31c9
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/css/css-overflow/scrollbar-gutter-reflow-counts-001.html.ini
@@ -0,0 +1,24 @@
+[scrollbar-gutter-reflow-counts-001.html]
+ [Enlarge the child's block-size to 200%]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
+
+ [Enlarge the child's block-size to 300px]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
+
+ [Enlarge the child's block-size to 200% in a vertical-lr scroll container]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
+
+ [Enlarge the child's block-size to 300px in a vertical-lr scroll container]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
+
+ [Enlarge the child's block-size to 200% in a vertical-rl scroll container]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
+
+ [Enlarge the child's block-size to 300px in a vertical-rl scroll container]
+ expected:
+ if os == "android": FAIL # Overlay scrollbars do not create scrollbar gutters.
diff --git a/testing/web-platform/mozilla/meta/css/cssom/window_size_rounding.html.ini b/testing/web-platform/mozilla/meta/css/cssom/window_size_rounding.html.ini
new file mode 100644
index 0000000000..c8cba67eee
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/css/cssom/window_size_rounding.html.ini
@@ -0,0 +1,5 @@
+[window_size_rounding.html]
+ bug: Different viewport size
+ [window_size_rounding]
+ expected:
+ if os == "android": FAIL
diff --git a/testing/web-platform/mozilla/meta/css/iframe-os-text-scale-print.sub.html.ini b/testing/web-platform/mozilla/meta/css/iframe-os-text-scale-print.sub.html.ini
new file mode 100644
index 0000000000..66d7433f03
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/css/iframe-os-text-scale-print.sub.html.ini
@@ -0,0 +1,5 @@
+prefs: [ui.textScaleFactor:200]
+[iframe-os-text-scale-print.sub.html]
+ expected:
+ if os == "linux": [PASS, FAIL]
+ if os == "win": [PASS, FAIL]
diff --git a/testing/web-platform/mozilla/meta/css/mediaqueries/mq-gamut-resist-fingerprinting.html.ini b/testing/web-platform/mozilla/meta/css/mediaqueries/mq-gamut-resist-fingerprinting.html.ini
new file mode 100644
index 0000000000..d6641989c9
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/css/mediaqueries/mq-gamut-resist-fingerprinting.html.ini
@@ -0,0 +1,2 @@
+[mq-gamut-resist-fingerprinting.html]
+ prefs: [privacy.resistFingerprinting:true]
diff --git a/testing/web-platform/mozilla/meta/dom/delayed_window_print.html.ini b/testing/web-platform/mozilla/meta/dom/delayed_window_print.html.ini
new file mode 100644
index 0000000000..71e21562eb
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/delayed_window_print.html.ini
@@ -0,0 +1,6 @@
+bug: https://bugzilla.mozilla.org/show_bug.cgi?id=739038
+[delayed_window_print.html]
+ comment: Our own save-to-pdf "printer" knows how to respect print.always_print_silent
+ prefs: [print.always_print_silent:true, "print_printer:Mozilla Save to PDF"]
+ disabled:
+ if (asan or debug): https://bugzilla.mozilla.org/show_bug.cgi?id=1661162
diff --git a/testing/web-platform/mozilla/meta/dom/range-in-two-selections.html.ini b/testing/web-platform/mozilla/meta/dom/range-in-two-selections.html.ini
new file mode 100644
index 0000000000..3602b3db5b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/range-in-two-selections.html.ini
@@ -0,0 +1 @@
+prefs: [dom.customHighlightAPI.enabled:true]
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/__dir__.ini b/testing/web-platform/mozilla/meta/dom/throttling/__dir__.ini
new file mode 100644
index 0000000000..2c01fc801d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/__dir__.ini
@@ -0,0 +1,5 @@
+prefs: [dom.timeout.enable_budget_timer_throttling:true,
+ dom.timeout.foreground_budget_regeneration_rate:100,
+ dom.timeout.foreground_throttling_max_budget:10,
+ dom.timeout.budget_throttling_max_delay:2000,
+ dom.timeout.throttling_delay:1]
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-1.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-1.window.js.ini
new file mode 100644
index 0000000000..99a37fb0e7
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-1.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-1.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-2.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-2.window.js.ini
new file mode 100644
index 0000000000..3ef84823d4
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-2.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-2.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-3.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-3.window.js.ini
new file mode 100644
index 0000000000..04fc9caa02
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-3.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-3.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-4.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-4.window.js.ini
new file mode 100644
index 0000000000..efb637225f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-4.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-4.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-indexeddb.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-indexeddb.window.js.ini
new file mode 100644
index 0000000000..e462d45d21
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-indexeddb.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-indexeddb.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-webaudio.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-webaudio.window.js.ini
new file mode 100644
index 0000000000..6322e40b6d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-webaudio.window.js.ini
@@ -0,0 +1,5 @@
+[throttling-webaudio.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
+ if (os == 'win' and processor == 'aarch64'): https://bugzilla.mozilla.org/show_bug.cgi?id=1533892 if (os == 'win' and processor == 'aarch64'): disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-webrtc.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-webrtc.window.js.ini
new file mode 100644
index 0000000000..f3f12fb571
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-webrtc.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-webrtc.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/dom/throttling/throttling-ws.window.js.ini b/testing/web-platform/mozilla/meta/dom/throttling/throttling-ws.window.js.ini
new file mode 100644
index 0000000000..219764bcca
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/dom/throttling/throttling-ws.window.js.ini
@@ -0,0 +1,4 @@
+[throttling-ws.window.html]
+ type: testharness
+ disabled:
+ if debug: disabled
diff --git a/testing/web-platform/mozilla/meta/editor/delete-space-after-double-click-selection.html.ini b/testing/web-platform/mozilla/meta/editor/delete-space-after-double-click-selection.html.ini
new file mode 100644
index 0000000000..690b6cbe0a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/editor/delete-space-after-double-click-selection.html.ini
@@ -0,0 +1,6 @@
+[delete-space-after-double-click-selection.html]
+ [DIV: Only one whitespace character should be removed when there are multiple.]
+ expected: FAIL
+
+ [DIV: Only one whitespace character should be removed when there are multiple whitespaces and the deleted range is the end of the string.]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/fetch/api/redirect/redirect-referrer.https.html.ini b/testing/web-platform/mozilla/meta/fetch/api/redirect/redirect-referrer.https.html.ini
new file mode 100644
index 0000000000..e934862b92
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/fetch/api/redirect/redirect-referrer.https.html.ini
@@ -0,0 +1,3 @@
+[redirect-referrer.https.html]
+ type: testharness
+ prefs: [security.mixed_content.block_active_content:false, security.mixed_content.block_display_content:false]
diff --git a/testing/web-platform/mozilla/meta/fetch/orb/__dir__.ini b/testing/web-platform/mozilla/meta/fetch/orb/__dir__.ini
new file mode 100644
index 0000000000..48c6803103
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/fetch/orb/__dir__.ini
@@ -0,0 +1,3 @@
+prefs: [browser.opaqueResponseBlocking:true,
+ browser.opaqueResponseBlocking.javascriptValidator:true,
+ browser.opaqueResponseBlocking.filterFetchResponse:2]
diff --git a/testing/web-platform/mozilla/meta/focus/Selection_extend.html.ini b/testing/web-platform/mozilla/meta/focus/Selection_extend.html.ini
new file mode 100644
index 0000000000..541e964a2d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/focus/Selection_extend.html.ini
@@ -0,0 +1,20 @@
+[Selection_extend.html]
+ type: testharness
+ [Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'outerEditor']
+ expected: FAIL
+
+ [Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'innerEditor']
+ expected: FAIL
+
+ [Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'editor']
+ expected: FAIL
+
+ [Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'outerEditor']
+ expected: FAIL
+
+ [Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'staticInEditor']
+ expected: FAIL
+
+ [Active element should be 'innerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'anchor']
+ expected: FAIL
+
diff --git a/testing/web-platform/mozilla/meta/focus/focus-next-tick-before-iframe-loaded-different-site.html.ini b/testing/web-platform/mozilla/meta/focus/focus-next-tick-before-iframe-loaded-different-site.html.ini
new file mode 100644
index 0000000000..ef5535b108
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/focus/focus-next-tick-before-iframe-loaded-different-site.html.ini
@@ -0,0 +1,4 @@
+[focus-next-tick-before-iframe-loaded-different-site.html]
+ [Check result]
+ expected:
+ ["PASS", "FAIL"]
diff --git a/testing/web-platform/mozilla/meta/html/semantics/scripting-1/the-script-element/__dir__.ini b/testing/web-platform/mozilla/meta/html/semantics/scripting-1/the-script-element/__dir__.ini
new file mode 100644
index 0000000000..ac824e7911
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/html/semantics/scripting-1/the-script-element/__dir__.ini
@@ -0,0 +1 @@
+prefs: [dom.moduleScripts.enabled:true]
diff --git a/testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini b/testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini
new file mode 100644
index 0000000000..1894b82e0f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/html/syntax/parsing/math-parse01.html.ini
@@ -0,0 +1,3 @@
+[math-parse01.html]
+ type: testharness
+ prefs: [mathml.disabled:true]
diff --git a/testing/web-platform/mozilla/meta/infrastructure/prefs/prefs-1.html.ini b/testing/web-platform/mozilla/meta/infrastructure/prefs/prefs-1.html.ini
new file mode 100644
index 0000000000..e106f6c252
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/infrastructure/prefs/prefs-1.html.ini
@@ -0,0 +1,2 @@
+[prefs-1.html]
+ prefs: [apz.allow_zooming_out:true]
diff --git a/testing/web-platform/mozilla/meta/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html.ini b/testing/web-platform/mozilla/meta/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html.ini
new file mode 100644
index 0000000000..9b845b0634
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html.ini
@@ -0,0 +1,3 @@
+[mathvariant-basic-transforms-with-default-font.html]
+ expected:
+ if os == "android": FAIL
diff --git a/testing/web-platform/mozilla/meta/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini b/testing/web-platform/mozilla/meta/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini
new file mode 100644
index 0000000000..123c4cd729
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini
@@ -0,0 +1,6 @@
+[MediaDevices-enumerateDevices.https.html]
+ prefs: [media.devices.enumerate.legacy.enabled:true]
+ expected:
+ if (os == "android") and fission: [OK, TIMEOUT]
+ [InputDeviceInfo is supported]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/mediacapture-streams/enumerateDevices-in-background.https.html.ini b/testing/web-platform/mozilla/meta/mediacapture-streams/enumerateDevices-in-background.https.html.ini
new file mode 100644
index 0000000000..0b5b37ae28
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/mediacapture-streams/enumerateDevices-in-background.https.html.ini
@@ -0,0 +1,3 @@
+[enumerateDevices-in-background.https.html]
+ disabled:
+ if buildapp != 'browser': uses Firefox-for-Desktop specific API
diff --git a/testing/web-platform/mozilla/meta/screen-capture/getdisplaymedia-user-activation-consumed.https.html.ini b/testing/web-platform/mozilla/meta/screen-capture/getdisplaymedia-user-activation-consumed.https.html.ini
new file mode 100644
index 0000000000..edce878a20
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/screen-capture/getdisplaymedia-user-activation-consumed.https.html.ini
@@ -0,0 +1,5 @@
+[getdisplaymedia-user-activation-consumed.https.html]
+ [Test getDisplayMedia() after user activation is consumed]
+ expected:
+ if os == "android": FAIL
+
diff --git a/testing/web-platform/mozilla/meta/wasm/__dir__.ini b/testing/web-platform/mozilla/meta/wasm/__dir__.ini
new file mode 100644
index 0000000000..bcdf039b0e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/wasm/__dir__.ini
@@ -0,0 +1 @@
+prefs: [javascript.options.wasm:true]
diff --git a/testing/web-platform/mozilla/meta/webdriver/__dir__.ini b/testing/web-platform/mozilla/meta/webdriver/__dir__.ini
new file mode 100644
index 0000000000..75fa14ee1e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/__dir__.ini
@@ -0,0 +1 @@
+lsan-allowed: [Alloc, Realloc, XPCNativeInterface::NewInstance, XPCNativeSet::NewInstance, XPCWrappedNative::GetNewOrUsed, XPCWrappedNativeProto::GetNewOrUsed, XPCWrappedNativeTearOff::AddTearOff, AddTearOff, mozilla::extensions::AtomSet::Get, mozilla::extensions::MatchPattern::Constructor, mozilla::extensions::MatchPattern::Init, InitializeStaticHeaders, nsDynamicAtom::Create]
diff --git a/testing/web-platform/mozilla/meta/webdriver/bidi/__dir__.ini b/testing/web-platform/mozilla/meta/webdriver/bidi/__dir__.ini
new file mode 100644
index 0000000000..daf68383df
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/bidi/__dir__.ini
@@ -0,0 +1 @@
+leak-threshold: [default:51200]
diff --git a/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/reference_context.py.ini b/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/reference_context.py.ini
new file mode 100644
index 0000000000..354cf0417e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/reference_context.py.ini
@@ -0,0 +1,4 @@
+[reference_context.py]
+ [test_reference_context]
+ disabled:
+ if os == "android": Not supported
diff --git a/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/type_hint.py.ini b/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/type_hint.py.ini
new file mode 100644
index 0000000000..1f7dbfcfb5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/bidi/browsing_context/create/type_hint.py.ini
@@ -0,0 +1,9 @@
+[type_hint.py]
+ [test_type_hint[tab\]]
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1795346
+ expected:
+ if os == "android": FAIL
+
+ [test_type_hint[window\]]
+ disabled:
+ if os == "android": Not supported
diff --git a/testing/web-platform/mozilla/meta/webdriver/bidi/interface/interface.py.ini b/testing/web-platform/mozilla/meta/webdriver/bidi/interface/interface.py.ini
new file mode 100644
index 0000000000..8a597d7ffe
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/bidi/interface/interface.py.ini
@@ -0,0 +1,4 @@
+[interface.py]
+ [test_navigator_webdriver_enabled]
+ disabled:
+ if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762135
diff --git a/testing/web-platform/mozilla/meta/webdriver/bidi/websocket_upgrade.py.ini b/testing/web-platform/mozilla/meta/webdriver/bidi/websocket_upgrade.py.ini
new file mode 100644
index 0000000000..c6e13dcecd
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/bidi/websocket_upgrade.py.ini
@@ -0,0 +1,3 @@
+[websocket_upgrade.py]
+ disabled:
+ if os == "android": https://bugzilla.mozilla.org/show_bug.cgi?id=1762164
diff --git a/testing/web-platform/mozilla/meta/webdriver/cdp/debugger_address.py.ini b/testing/web-platform/mozilla/meta/webdriver/cdp/debugger_address.py.ini
new file mode 100644
index 0000000000..59480e656d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/cdp/debugger_address.py.ini
@@ -0,0 +1,11 @@
+[debugger_address.py]
+ disabled:
+ if os == 'win' and ccov: https://bugzilla.mozilla.org/show_bug.cgi?id=1677750
+
+ [test_debugger_address_true_with_fission[capabilities0-enabled\]]
+ disabled:
+ if not fission: not supported
+
+ [test_debugger_address_true_with_fission[capabilities0-disabled\]]
+ disabled:
+ if fission: not supported
diff --git a/testing/web-platform/mozilla/meta/webdriver/cdp/port_file.py.ini b/testing/web-platform/mozilla/meta/webdriver/cdp/port_file.py.ini
new file mode 100644
index 0000000000..bd43509a4e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/cdp/port_file.py.ini
@@ -0,0 +1,3 @@
+[port_file.py]
+ disabled:
+ if os == "android": https://bugzilla.mozilla.org/show_bug.cgi?id=1762164
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/execute_async_script/execute_async.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/execute_async_script/execute_async.py.ini
new file mode 100644
index 0000000000..98efbecd45
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/execute_async_script/execute_async.py.ini
@@ -0,0 +1,16 @@
+[execute_async.py]
+ bug: [1789355, 1806999]
+ [test_no_abort_by_user_prompt_in_other_tab[alert\]]
+ expected:
+ if os == "android" or tsan: [PASS, FAIL]
+ PASS
+
+ [test_no_abort_by_user_prompt_in_other_tab[confirm\]]
+ expected:
+ if os == "android" or tsan: [PASS, FAIL]
+ PASS
+
+ [test_no_abort_by_user_prompt_in_other_tab[prompt\]]
+ expected:
+ if os == "android" or tsan: [PASS, FAIL]
+ PASS
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/get_window_handles/chrome.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/get_window_handles/chrome.py.ini
new file mode 100644
index 0000000000..4c686ef883
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/get_window_handles/chrome.py.ini
@@ -0,0 +1,4 @@
+[chrome.py]
+ [test_multiple_windows_and_tabs]
+ disabled:
+ if os == "android": Not supported
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/new_session/__dir__.ini b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/__dir__.ini
new file mode 100644
index 0000000000..4909cb7221
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/__dir__.ini
@@ -0,0 +1,2 @@
+lsan-allowed: [MakeUnique, XPCNativeSet::NewInstanceMutate, nsStringBuffer::Alloc, nsStringBundleService::insertIntoCache]
+leak-threshold: [default:150000]
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/new_session/binary.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/binary.py.ini
new file mode 100644
index 0000000000..515482e26f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/binary.py.ini
@@ -0,0 +1,4 @@
+[binary.py]
+ [test_shell_script_binary]
+ disabled:
+ if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762135
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/new_session/profile_root.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/profile_root.py.ini
new file mode 100644
index 0000000000..e2fcdc116f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/new_session/profile_root.py.ini
@@ -0,0 +1,4 @@
+[profile_root.py]
+ [test_profile_root]
+ expected:
+ if os == "android": FAIL
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/protocol/marionette_port.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/protocol/marionette_port.py.ini
new file mode 100644
index 0000000000..04befe8e5d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/protocol/marionette_port.py.ini
@@ -0,0 +1,8 @@
+[marionette_port.py]
+ [test_marionette_port[system allocated\]]
+ disabled:
+ if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1752284
+
+ [test_marionette_port_outdated_active_port_file]
+ disabled:
+ if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1752284
diff --git a/testing/web-platform/mozilla/meta/webdriver/classic/send_alert_text.py.ini b/testing/web-platform/mozilla/meta/webdriver/classic/send_alert_text.py.ini
new file mode 100644
index 0000000000..0f70ffcc6d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webdriver/classic/send_alert_text.py.ini
@@ -0,0 +1,4 @@
+[send_alert_text.py]
+ [test_basic_auth_unsupported_operation]
+ disabled:
+ if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1761480
diff --git a/testing/web-platform/mozilla/meta/webgpu/__dir__.ini b/testing/web-platform/mozilla/meta/webgpu/__dir__.ini
new file mode 100644
index 0000000000..a09dfa9380
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/__dir__.ini
@@ -0,0 +1,5 @@
+prefs: [dom.webgpu.enabled:true]
+tags: [webgpu]
+disabled:
+ if release_or_beta: https://mozilla-hub.atlassian.net/browse/FFXP-223
+ if os == "mac": https://mozilla-hub.atlassian.net/browse/FFXP-223
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/1/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/1/cts.https.html.ini
new file mode 100644
index 0000000000..9bdf77480d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/1/cts.https.html.ini
@@ -0,0 +1,823 @@
+[cts.https.html?q=webgpu:api,operation,adapter,requestAdapter:requestAdapter:*]
+ [:powerPreference="_undef_";forceFallbackAdapter="_undef_"]
+ expected: FAIL
+
+ [:powerPreference="_undef_";forceFallbackAdapter=false]
+ expected: FAIL
+
+ [:powerPreference="low-power";forceFallbackAdapter="_undef_"]
+ expected: FAIL
+
+ [:powerPreference="low-power";forceFallbackAdapter=false]
+ expected: FAIL
+
+ [:powerPreference="high-performance";forceFallbackAdapter="_undef_"]
+ expected: FAIL
+
+ [:powerPreference="high-performance";forceFallbackAdapter=false]
+ expected: FAIL
+
+ [:powerPreference="_undef_";forceFallbackAdapter=true]
+ expected:
+ if os == "win": FAIL
+ # This intermittently fails on Linux shippable.
+ # See <https://bugzilla.mozilla.org/show_bug.cgi?id=1824038>.
+ if os == "linux": [PASS, FAIL]
+ PASS
+
+ [:powerPreference="low-power";forceFallbackAdapter=true]
+ expected:
+ if os == "win": FAIL
+ # This intermittently fails on Linux shippable.
+ # See <https://bugzilla.mozilla.org/show_bug.cgi?id=1824038>.
+ if os == "linux": [PASS, FAIL]
+ PASS
+
+ [:powerPreference="high-performance";forceFallbackAdapter=true]
+ expected:
+ if os == "win": FAIL
+ # This intermittently fails on Linux shippable.
+ # See <https://bugzilla.mozilla.org/show_bug.cgi?id=1824038>.
+ if os == "linux": [PASS, FAIL]
+ PASS
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:default:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:limits,unknown:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map_detach:while_mapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,threading:serialize:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mappedAtCreation:*]
+ [:mappable=false]
+ expected: FAIL
+
+ [:mappable=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestAdapterInfo:adapter_info_with_hints:*]
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:remapped_for_write:*]
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map_ArrayBuffer:postMessage:*]
+ [:transfer=false;mapMode="READ"]
+ expected: FAIL
+
+ [:transfer=false;mapMode="WRITE"]
+ expected: FAIL
+
+ [:transfer=true;mapMode="READ"]
+ expected: FAIL
+
+ [:transfer=true;mapMode="WRITE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation:*]
+ [:oom=false;size=16]
+ expected: FAIL
+
+ [:oom=true;size=9007199254740984]
+ expected: FAIL
+
+ [:oom=true;size=137438953472]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mappedAtCreation,mapState:*]
+ [:validationError=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:validationError=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:validationError=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:validationError=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:validationError=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:validationError=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:validationError=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:validationError=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,mapState:*]
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=false;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=false;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=false;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=false;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=false;afterDestroy=true]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=false]
+ expected: FAIL
+
+ [:bufferCreationValidationError=true;mapAsyncValidationError=true;beforeUnmap=true;beforeDestroy=true;afterUnmap=true;afterDestroy=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:invalid:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,write,unchanged_ranges_preserved:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:limits,supported:*]
+ [:limit="maxTextureDimension1D"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxTextureDimension2D"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxTextureDimension3D"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxTextureArrayLayers"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxBindGroups"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxDynamicUniformBuffersPerPipelineLayout"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxDynamicStorageBuffersPerPipelineLayout"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxSampledTexturesPerShaderStage"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxSamplersPerShaderStage"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxStorageBuffersPerShaderStage"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxStorageTexturesPerShaderStage"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxUniformBuffersPerShaderStage"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxUniformBufferBindingSize"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxStorageBufferBindingSize"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="minUniformBufferOffsetAlignment"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="minStorageBufferOffsetAlignment"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxVertexBuffers"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxBufferSize"]
+ expected: FAIL
+
+ [:limit="maxVertexAttributes"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxVertexBufferArrayStride"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxInterStageShaderComponents"]
+ expected: FAIL
+
+ [:limit="maxColorAttachments"]
+ expected: FAIL
+
+ [:limit="maxColorAttachmentBytesPerSample"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupStorageSize"]
+ expected: FAIL
+
+ [:limit="maxComputeInvocationsPerWorkgroup"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeX"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxComputeWorkgroupSizeY"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxComputeWorkgroupSizeZ"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:limit="maxComputeWorkgroupsPerDimension"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:features,unknown:*]
+ [:]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:features,known:*]
+ [:feature="depth-clip-control"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:feature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:feature="texture-compression-bc"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:feature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:feature="texture-compression-astc"]
+ expected: FAIL
+
+ [:feature="timestamp-query"]
+ expected: FAIL
+
+ [:feature="indirect-first-instance"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:feature="shader-f16"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:feature="rg11b10ufloat-renderable"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,write:*]
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestAdapterInfo:adapter_info:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:limit,better_than_supported:*]
+ [:limit="maxTextureDimension1D"]
+ expected: FAIL
+
+ [:limit="maxTextureDimension2D"]
+ expected: FAIL
+
+ [:limit="maxTextureDimension3D"]
+ expected: FAIL
+
+ [:limit="maxTextureArrayLayers"]
+ expected: FAIL
+
+ [:limit="maxBindGroups"]
+ expected: FAIL
+
+ [:limit="maxDynamicUniformBuffersPerPipelineLayout"]
+ expected: FAIL
+
+ [:limit="maxDynamicStorageBuffersPerPipelineLayout"]
+ expected: FAIL
+
+ [:limit="maxSampledTexturesPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxSamplersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxStorageBuffersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxStorageTexturesPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxUniformBuffersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxUniformBufferBindingSize"]
+ expected: FAIL
+
+ [:limit="maxStorageBufferBindingSize"]
+ expected: FAIL
+
+ [:limit="minUniformBufferOffsetAlignment"]
+ expected: FAIL
+
+ [:limit="minStorageBufferOffsetAlignment"]
+ expected: FAIL
+
+ [:limit="maxVertexBuffers"]
+ expected: FAIL
+
+ [:limit="maxBufferSize"]
+ expected: FAIL
+
+ [:limit="maxVertexAttributes"]
+ expected: FAIL
+
+ [:limit="maxVertexBufferArrayStride"]
+ expected: FAIL
+
+ [:limit="maxInterStageShaderComponents"]
+ expected: FAIL
+
+ [:limit="maxColorAttachments"]
+ expected: FAIL
+
+ [:limit="maxColorAttachmentBytesPerSample"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupStorageSize"]
+ expected: FAIL
+
+ [:limit="maxComputeInvocationsPerWorkgroup"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeX"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeY"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeZ"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupsPerDimension"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map_oom:mapAsync:*]
+ [:oom=false;size=16]
+ expected: FAIL
+
+ [:oom=true;size=9007199254740984]
+ expected: FAIL
+
+ [:oom=true;size=137438953472]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestAdapter:requestAdapter_no_parameters:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,read:*]
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,adapter,requestDevice:limit,worse_than_default:*]
+ [:limit="maxTextureDimension1D"]
+ expected: FAIL
+
+ [:limit="maxTextureDimension2D"]
+ expected: FAIL
+
+ [:limit="maxTextureDimension3D"]
+ expected: FAIL
+
+ [:limit="maxTextureArrayLayers"]
+ expected: FAIL
+
+ [:limit="maxBindGroups"]
+ expected: FAIL
+
+ [:limit="maxDynamicUniformBuffersPerPipelineLayout"]
+ expected: FAIL
+
+ [:limit="maxDynamicStorageBuffersPerPipelineLayout"]
+ expected: FAIL
+
+ [:limit="maxSampledTexturesPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxSamplersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxStorageBuffersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxStorageTexturesPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxUniformBuffersPerShaderStage"]
+ expected: FAIL
+
+ [:limit="maxUniformBufferBindingSize"]
+ expected: FAIL
+
+ [:limit="maxStorageBufferBindingSize"]
+ expected: FAIL
+
+ [:limit="minUniformBufferOffsetAlignment"]
+ expected: FAIL
+
+ [:limit="minStorageBufferOffsetAlignment"]
+ expected: FAIL
+
+ [:limit="maxVertexBuffers"]
+ expected: FAIL
+
+ [:limit="maxBufferSize"]
+ expected: FAIL
+
+ [:limit="maxVertexAttributes"]
+ expected: FAIL
+
+ [:limit="maxVertexBufferArrayStride"]
+ expected: FAIL
+
+ [:limit="maxInterStageShaderComponents"]
+ expected: FAIL
+
+ [:limit="maxColorAttachments"]
+ expected: FAIL
+
+ [:limit="maxColorAttachmentBytesPerSample"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupStorageSize"]
+ expected: FAIL
+
+ [:limit="maxComputeInvocationsPerWorkgroup"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeX"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeY"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupSizeZ"]
+ expected: FAIL
+
+ [:limit="maxComputeWorkgroupsPerDimension"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,map:mapAsync,read,typedArrayAccess:*]
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="default-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="explicit-expand";mapAsyncRegionRight="minimal"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="default-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="explicit-expand"]
+ expected: FAIL
+
+ [:mapAsyncRegionLeft="minimal";mapAsyncRegionRight="minimal"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/10/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/10/cts.https.html.ini
new file mode 100644
index 0000000000..e29fc26d83
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/10/cts.https.html.ini
@@ -0,0 +1,456 @@
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,unmapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_descriptor:*]
+ [:format="depth32float-stencil8";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,query_types:createQuerySet:*]
+ [:type="occlusion";featureContainsTimestampQuery=false]
+ expected: FAIL
+
+ [:type="timestamp";featureContainsTimestampQuery=false]
+ expected: FAIL
+
+ [:type="occlusion";featureContainsTimestampQuery=true]
+ expected: FAIL
+
+ [:type="timestamp";featureContainsTimestampQuery=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,invalid_mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:unmap,state,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:gc_behavior,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mapped:*]
+ [:mapMode=1]
+ expected: FAIL
+
+ [:mapMode=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjointRanges:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:unmap,state,unmapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:unmap,state,destroyed:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAgain:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:gc_behavior,mapAsync:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappingPending:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjoinRanges_many:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,destroyed:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:unmap,state,mappingPending:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,query_types:writeTimestamp:*]
+ [:featureContainsTimestampQuery=false]
+ expected: FAIL
+
+ [:featureContainsTimestampQuery=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mapped:*]
+ [:mapMode=1]
+ expected: FAIL
+
+ [:mapMode=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:unmap,state,mapped:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/11/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/11/cts.https.html.ini
new file mode 100644
index 0000000000..53379d9344
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/11/cts.https.html.ini
@@ -0,0 +1,2531 @@
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:shader_module,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:canvas_configuration:*]
+ [:format="depth32float-stencil8";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11snorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11snorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11snorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11snorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits:*]
+ [:isAsync=true;type="u32"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,value,type_error:*]
+ [:isAsync=true;constants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:basic:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits,workgroup_storage_size:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:shader_module,compute:*]
+ [:isAsync=true;shaderModuleStage="compute"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleStage="vertex"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleStage="fragment"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleStage="compute"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleStage="vertex"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleStage="fragment"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:pipeline_layout,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,value,validation_error,f16:*]
+ [:isAsync=true;constants={"cf16":-65504}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":-98288}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":65504}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":98288}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf16":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":-65504}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":-98288}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":65504}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":98288}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf16":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,value,validation_error:*]
+ [:isAsync=true;constants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"cb":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"cb":-2147483649}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:binding_must_contain_resource_defined_in_layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:limits,invocations_per_workgroup,each_component:*]
+ [:isAsync=true;size=[64\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[256,1,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[257,1,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,256,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,257,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,1,63\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,1,64\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,1,65\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[64\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[256,1,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[257,1,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,256,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,257,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,1,63\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,1,64\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,1,65\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size:*]
+ [:isAsync=true;type="u32";constants={}]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";constants={"x":0,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";constants={"x":1,"y":-1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";constants={"x":1,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";constants={"x":16,"y":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";constants={}]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";constants={"x":0,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";constants={"x":1,"y":-1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";constants={"x":1,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";constants={"x":16,"y":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";constants={}]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";constants={"x":0,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";constants={"x":1,"y":-1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";constants={"x":1,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";constants={"x":16,"y":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";constants={}]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";constants={"x":0,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";constants={"x":1,"y":-1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";constants={"x":1,"y":0,"z":0}]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";constants={"x":16,"y":1,"z":1}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:binding_count_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_descriptor_view_formats:*]
+ [:format="depth32float-stencil8";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:render_bundle_encoder_descriptor_depth_stencil_format:*]
+ [:format="depth32float-stencil8";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";enable_required_feature=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_view_descriptor:*]
+ [:format="depth32float-stencil8";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-r11snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";enable_required_feature=true]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";enable_required_feature=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:depth_stencil_state:*]
+ [:format="depth32float-stencil8";enable_required_feature=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";enable_required_feature=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:shader_module,invalid:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:binding_must_be_present_in_layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,uninitialized:*]
+ [:isAsync=true;constants={}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c0":0,"c2":0,"c8":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c0":0,"c2":0,"c5":0,"c8":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c0":0,"c2":0,"c5":0,"c8":0,"c1":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c0":0,"c2":0,"c8":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c0":0,"c2":0,"c5":0,"c8":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c0":0,"c2":0,"c5":0,"c8":0,"c1":0}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:overrides,identifier:*]
+ [:isAsync=true;constants={}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c0":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c0":0,"c1":1}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c9":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"1":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"c3":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"2":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"1000":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"9999":0}]
+ expected: FAIL
+
+ [:isAsync=true;constants={"1000":0,"c2":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c0":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c0":0,"c1":1}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c9":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"1":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"c3":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"2":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"1000":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"9999":0}]
+ expected: FAIL
+
+ [:isAsync=false;constants={"1000":0,"c2":0}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,capability_checks,features,texture_formats:canvas_configuration_view_formats:*]
+ [:viewFormats=["depth32float-stencil8"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["depth32float-stencil8"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc2-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc3-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-snorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-snorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-snorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc4-r-snorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-snorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-snorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-snorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc5-rg-snorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-ufloat"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-ufloat"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-ufloat"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-ufloat"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-float"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-float"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-float"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc6h-rgb-float"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc7-rgba-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11snorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11snorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11snorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11snorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x4-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-5x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-6x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-8x8-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x5-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x6-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x8-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-10x10-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x10-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm-srgb"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-12x12-unorm-srgb"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bgra8unorm","bc1-rgba-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bgra8unorm","bc1-rgba-unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bgra8unorm","bc1-rgba-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bgra8unorm","bc1-rgba-unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm","bgra8unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm","bgra8unorm"\];canvasType="onscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm","bgra8unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["bc1-rgba-unorm","bgra8unorm"\];canvasType="offscreen";enable_required_feature=false]
+ expected: FAIL
+
+ [:viewFormats=["depth32float-stencil8"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["depth32float-stencil8"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgb8a1unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm-srgb"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["etc2-rgba8unorm-srgb"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11snorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-r11snorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11snorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["eac-rg11snorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm"\];canvasType="onscreen";enable_required_feature=true]
+ expected: FAIL
+
+ [:viewFormats=["astc-4x4-unorm"\];canvasType="offscreen";enable_required_feature=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:limits,invocations_per_workgroup:*]
+ [:isAsync=true;size=[128,1,2\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[129,1,2\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[2,128,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[2,129,1\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,8,32\]]
+ expected: FAIL
+
+ [:isAsync=true;size=[1,8,33\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[128,1,2\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[129,1,2\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[2,128,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[2,129,1\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,8,32\]]
+ expected: FAIL
+
+ [:isAsync=false;size=[1,8,33\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,compute_pipeline:limits,workgroup_storage_size:*]
+ [:isAsync=true;type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=true;type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=false;type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=false;type="mat4x4%3Cf32%3E"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/12/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/12/cts.https.html.ini
new file mode 100644
index 0000000000..c617dd1800
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/12/cts.https.html.ini
@@ -0,0 +1,1125 @@
+[cts.https.html?q=webgpu:api,validation,createBindGroup:binding_resources,device_mismatch:*]
+ [:entry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:entry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:visibility,VERTEX_shader_stage_buffer_type:*]
+ [:shaderStage=0]
+ expected: FAIL
+
+ [:shaderStage=1]
+ expected: FAIL
+
+ [:shaderStage=2]
+ expected: FAIL
+
+ [:shaderStage=3]
+ expected: FAIL
+
+ [:shaderStage=4]
+ expected: FAIL
+
+ [:shaderStage=5]
+ expected: FAIL
+
+ [:shaderStage=6]
+ expected: FAIL
+
+ [:shaderStage=7]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:sampler,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:visibility:*]
+ [:visibility=0]
+ expected: FAIL
+
+ [:visibility=1]
+ expected: FAIL
+
+ [:visibility=2]
+ expected: FAIL
+
+ [:visibility=3]
+ expected: FAIL
+
+ [:visibility=4]
+ expected: FAIL
+
+ [:visibility=5]
+ expected: FAIL
+
+ [:visibility=6]
+ expected: FAIL
+
+ [:visibility=7]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer,resource_binding_size:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:storage_texture,usage:*]
+ [:usage0=1;usage1=1]
+ expected: FAIL
+
+ [:usage0=1;usage1=2]
+ expected: FAIL
+
+ [:usage0=1;usage1=4]
+ expected: FAIL
+
+ [:usage0=1;usage1=8]
+ expected: FAIL
+
+ [:usage0=1;usage1=16]
+ expected: FAIL
+
+ [:usage0=2;usage1=1]
+ expected: FAIL
+
+ [:usage0=2;usage1=2]
+ expected: FAIL
+
+ [:usage0=2;usage1=4]
+ expected: FAIL
+
+ [:usage0=2;usage1=8]
+ expected: FAIL
+
+ [:usage0=2;usage1=16]
+ expected: FAIL
+
+ [:usage0=4;usage1=1]
+ expected: FAIL
+
+ [:usage0=4;usage1=2]
+ expected: FAIL
+
+ [:usage0=4;usage1=4]
+ expected: FAIL
+
+ [:usage0=4;usage1=8]
+ expected: FAIL
+
+ [:usage0=4;usage1=16]
+ expected: FAIL
+
+ [:usage0=8;usage1=1]
+ expected: FAIL
+
+ [:usage0=8;usage1=2]
+ expected: FAIL
+
+ [:usage0=8;usage1=4]
+ expected: FAIL
+
+ [:usage0=8;usage1=8]
+ expected: FAIL
+
+ [:usage0=8;usage1=16]
+ expected: FAIL
+
+ [:usage0=16;usage1=1]
+ expected: FAIL
+
+ [:usage0=16;usage1=2]
+ expected: FAIL
+
+ [:usage0=16;usage1=4]
+ expected: FAIL
+
+ [:usage0=16;usage1=8]
+ expected: FAIL
+
+ [:usage0=16;usage1=16]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:visibility,VERTEX_shader_stage_storage_texture_access:*]
+ [:shaderStage=0]
+ expected: FAIL
+
+ [:shaderStage=1]
+ expected: FAIL
+
+ [:shaderStage=2]
+ expected: FAIL
+
+ [:shaderStage=3]
+ expected: FAIL
+
+ [:shaderStage=4]
+ expected: FAIL
+
+ [:shaderStage=5]
+ expected: FAIL
+
+ [:shaderStage=6]
+ expected: FAIL
+
+ [:shaderStage=7]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:multisampled_validation:*]
+ [:viewDimension="_undef_"]
+ expected: FAIL
+
+ [:viewDimension="1d"]
+ expected: FAIL
+
+ [:viewDimension="2d"]
+ expected: FAIL
+
+ [:viewDimension="2d-array"]
+ expected: FAIL
+
+ [:viewDimension="cube"]
+ expected: FAIL
+
+ [:viewDimension="cube-array"]
+ expected: FAIL
+
+ [:viewDimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_dimension:*]
+ [:usage=4;viewDimension="1d"]
+ expected: FAIL
+
+ [:usage=4;viewDimension="2d"]
+ expected: FAIL
+
+ [:usage=4;viewDimension="2d-array"]
+ expected: FAIL
+
+ [:usage=4;viewDimension="cube"]
+ expected: FAIL
+
+ [:usage=4;viewDimension="cube-array"]
+ expected: FAIL
+
+ [:usage=4;viewDimension="3d"]
+ expected: FAIL
+
+ [:usage=8;viewDimension="1d"]
+ expected: FAIL
+
+ [:usage=8;viewDimension="2d"]
+ expected: FAIL
+
+ [:usage=8;viewDimension="2d-array"]
+ expected: FAIL
+
+ [:usage=8;viewDimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:duplicate_bindings:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer,usage:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:minBindingSize:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:maximum_binding_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:storage_texture,mip_level_count:*]
+ [:baseMipLevel=1;mipLevelCount=1]
+ expected: FAIL
+
+ [:baseMipLevel=1;mipLevelCount=2]
+ expected: FAIL
+
+ [:baseMipLevel=2;mipLevelCount=1]
+ expected: FAIL
+
+ [:baseMipLevel=2;mipLevelCount=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:sampler,compare_function_with_binding_type:*]
+ [:bgType="filtering"]
+ expected: FAIL
+
+ [:bgType="non-filtering"]
+ expected: FAIL
+
+ [:bgType="comparison"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer,effective_buffer_binding_size:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer,resource_offset:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:multisampled_validation:*]
+ [:multisampled=true]
+ expected: FAIL
+
+ [:multisampled=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:bind_group_layout,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_component_type:*]
+ [:sampleType="float"]
+ expected: FAIL
+
+ [:sampleType="sint"]
+ expected: FAIL
+
+ [:sampleType="uint"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer_offset_and_size_for_bind_groups_match:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:texture,resource_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:storage_texture,format:*]
+ [:storageTextureFormat="r32uint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32uint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32sint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="r32float";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8unorm";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8snorm";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8uint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba8sint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32uint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32sint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rg32float";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16uint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16sint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba16float";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32uint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32sint";resourceFormat="rgba32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="r32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="r32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="r32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba8snorm"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba8uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba8sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rg32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rg32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rg32float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba16uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba16sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba16float"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba32uint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba32sint"]
+ expected: FAIL
+
+ [:storageTextureFormat="rgba32float";resourceFormat="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:buffer,resource_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/13/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/13/cts.https.html.ini
new file mode 100644
index 0000000000..12d259d097
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/13/cts.https.html.ini
@@ -0,0 +1,15741 @@
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:storage_texture,layout_dimension:*]
+ [:viewDimension="_undef_"]
+ expected: FAIL
+
+ [:viewDimension="1d"]
+ expected: FAIL
+
+ [:viewDimension="2d"]
+ expected: FAIL
+
+ [:viewDimension="2d-array"]
+ expected: FAIL
+
+ [:viewDimension="cube"]
+ expected: FAIL
+
+ [:viewDimension="cube-array"]
+ expected: FAIL
+
+ [:viewDimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:sampleCount,various_sampleCount_with_all_formats:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createSampler:maxAnisotropy:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:mipLevelCount,format:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check,bigger_than_integer_bit_width:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,3d_texture,uncompressed_format:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,uncompressed_format:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:max_dynamic_buffers:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_pipeline_layout:*]
+ [:maxedEntry={"buffer":{"type":"uniform"}}]
+ expected: FAIL
+
+ [:maxedEntry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:maxedEntry={"buffer":{"type":"read-only-storage"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"comparison"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"non-filtering"}}]
+ expected: FAIL
+
+ [:maxedEntry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:maxedEntry={"texture":{"multisampled":true}}]
+ expected: FAIL
+
+ [:maxedEntry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:sample_count,1d_2d_array_3d:*]
+ [:dimension="2d";size=[4,4,1\];shouldError=false]
+ expected: FAIL
+
+ [:dimension="2d";size=[4,4,4\];shouldError=true]
+ expected: FAIL
+
+ [:dimension="2d";size=[4,4,6\];shouldError=true]
+ expected: FAIL
+
+ [:dimension="1d";size=[4,1,1\];shouldError=true]
+ expected: FAIL
+
+ [:dimension="3d";size=[4,4,4\];shouldError=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createPipelineLayout:number_of_dynamic_buffers_exceeds_the_maximum_value:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,1d_texture:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,3d_texture,compressed_format:*]
+
+[cts.https.html?q=webgpu:api,validation,createSampler:lodMinAndMaxClamp:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,2d_texture,compressed_format:*]
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8187,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[8197,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm";size=[5,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8187,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[8197,4,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,8188,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,8196,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,4,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,4,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb";size=[5,4,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8187,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[8197,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm";size=[5,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8187,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[8197,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb";size=[5,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8186,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[8198,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm";size=[6,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8186,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[8198,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb";size=[6,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8186,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[8198,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm";size=[6,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8186,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[8198,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb";size=[6,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8184,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8200,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm";size=[8,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8184,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8200,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb";size=[8,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8184,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8200,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm";size=[8,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8184,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8200,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb";size=[8,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8184,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8200,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm";size=[8,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8184,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8200,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb";size=[8,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8182,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[8202,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm";size=[10,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8182,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[8202,5,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,8187,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,8197,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,5,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,5,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb";size=[10,5,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8182,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[8202,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm";size=[10,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8182,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[8202,6,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,8186,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,8198,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,6,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,6,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb";size=[10,6,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8182,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[8202,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm";size=[10,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8182,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[8202,8,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8184,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8200,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb";size=[10,8,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8182,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[8202,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm";size=[10,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8182,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[8202,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb";size=[10,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8180,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[8204,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm";size=[12,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8180,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[8204,10,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,8182,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,8202,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,10,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,10,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb";size=[12,10,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8180,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8192,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[8204,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,8180,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,8180,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,12,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,12,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,12,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,12,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[1,12,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm";size=[12,12,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8180,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8192,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[8204,12,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,8180,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,8180,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,8204,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,12,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,12,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,12,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,12,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[1,12,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb";size=[12,12,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8188,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8188,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8196,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[8196,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb";size=[4,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8187,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[8197,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm";size=[5,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8187,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8192,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[8197,4,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,8188,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,8196,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,4,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,4,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[1,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb";size=[5,4,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8187,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[8197,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm";size=[5,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8187,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8187,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8197,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[8197,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb";size=[5,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8186,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[8198,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm";size=[6,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8186,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[8198,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb";size=[6,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8186,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[8198,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm";size=[6,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8186,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8186,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8198,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[8198,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb";size=[6,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8184,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8200,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm";size=[8,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8184,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8200,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb";size=[8,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8184,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8200,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm";size=[8,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8184,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8200,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb";size=[8,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8184,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8200,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm";size=[8,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8184,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8184,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8200,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8200,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb";size=[8,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8182,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[8202,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm";size=[10,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8182,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8192,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[8202,5,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,8187,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,8197,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,5,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,5,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[1,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb";size=[10,5,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8182,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[8202,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm";size=[10,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8182,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8192,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[8202,6,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,8186,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,8198,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,6,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,6,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[1,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb";size=[10,6,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8182,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[8202,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm";size=[10,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8182,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8192,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[8202,8,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8184,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8200,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[1,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb";size=[10,8,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8182,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[8202,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm";size=[10,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8182,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8182,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8202,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[8202,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb";size=[10,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8180,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[8204,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm";size=[12,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8180,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8192,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[8204,10,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,8182,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,8202,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,10,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,10,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[1,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb";size=[12,10,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8180,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8192,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[8204,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,8180,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,8180,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,12,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,12,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,12,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,12,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[1,12,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm";size=[12,12,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8180,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8180,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8192,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8204,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[8204,12,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,8180,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,8180,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,8204,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,12,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,12,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,12,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,12,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[1,12,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb";size=[12,12,257\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:zero_size_and_usage:*]
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,2d_texture,uncompressed_format:*]
+ [:dimension="_undef_";format="r8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[8191,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[8192,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[8193,1,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,8191,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,8192,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,8193,1\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,1,255\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,1,256\]]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8";size=[1,1,257\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:dimension_type_and_format_compatibility:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="1d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="1d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="1d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="3d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createPipelineLayout:number_of_bind_group_layouts_exceeds_the_maximum_value:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createPipelineLayout:bind_group_layouts,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:storage_texture,formats:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="eac-r11unorm"]
+ expected: FAIL
+
+ [:format="eac-r11snorm"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_bind_group_layout:*]
+ [:maxedEntry={"buffer":{"type":"uniform"}}]
+ expected: FAIL
+
+ [:maxedEntry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:maxedEntry={"buffer":{"type":"read-only-storage"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"comparison"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:maxedEntry={"sampler":{"type":"non-filtering"}}]
+ expected: FAIL
+
+ [:maxedEntry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:maxedEntry={"texture":{"multisampled":true}}]
+ expected: FAIL
+
+ [:maxedEntry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,compressed_format:*]
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/14/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/14/cts.https.html.ini
new file mode 100644
index 0000000000..fda4891f5d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/14/cts.https.html.ini
@@ -0,0 +1,2076 @@
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:default_args:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,same_location:*]
+ [:locationA="beginning";locationB="beginning"]
+ expected: FAIL
+
+ [:locationA="beginning";locationB="end"]
+ expected: FAIL
+
+ [:locationA="end";locationB="beginning"]
+ expected: FAIL
+
+ [:locationA="end";locationB="end"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,debugMarker:push_pop_call_count_unbalance,render_compute_pass:*]
+ [:passType="compute"]
+ expected: FAIL
+
+ [:passType="render"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,debugMarker:push_pop_call_count_unbalance,command_encoder:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginRenderPass:color_attachments,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,query_index_count:*]
+ [:queryIndex=0]
+ expected: FAIL
+
+ [:queryIndex=1]
+ expected: FAIL
+
+ [:queryIndex=2]
+ expected: FAIL
+
+ [:queryIndex=3]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:aspect:*]
+ [:format="r8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="r8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r8snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="r8snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r8snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r8uint";aspect="all"]
+ expected: FAIL
+
+ [:format="r8uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r8uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r8sint";aspect="all"]
+ expected: FAIL
+
+ [:format="r8sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r8sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r16uint";aspect="all"]
+ expected: FAIL
+
+ [:format="r16uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r16uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r16sint";aspect="all"]
+ expected: FAIL
+
+ [:format="r16sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r16sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r16float";aspect="all"]
+ expected: FAIL
+
+ [:format="r16float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r16float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="rg8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg8snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="rg8snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg8snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg8uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg8uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg8uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg8sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg8sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg8sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r32uint";aspect="all"]
+ expected: FAIL
+
+ [:format="r32uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r32uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r32sint";aspect="all"]
+ expected: FAIL
+
+ [:format="r32sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r32sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="r32float";aspect="all"]
+ expected: FAIL
+
+ [:format="r32float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="r32float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg16uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg16uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg16uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg16sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg16sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg16sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg16float";aspect="all"]
+ expected: FAIL
+
+ [:format="rg16float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg16float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba8snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba8snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba8snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba8uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba8uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba8uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba8sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba8sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba8sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bgra8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bgra8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bgra8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat";aspect="all"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat";aspect="all"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg32uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg32uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg32uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg32sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rg32sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg32sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rg32float";aspect="all"]
+ expected: FAIL
+
+ [:format="rg32float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rg32float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba16uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba16uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba16uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba16sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba16sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba16sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba16float";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba16float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba16float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba32uint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba32uint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba32uint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba32sint";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba32sint";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba32sint";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="rgba32float";aspect="all"]
+ expected: FAIL
+
+ [:format="rgba32float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="rgba32float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float";aspect="all"]
+ expected: FAIL
+
+ [:format="depth32float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth32float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="all"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus";aspect="all"]
+ expected: FAIL
+
+ [:format="depth24plus";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth24plus";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="all"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="all"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";aspect="all"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";aspect="all"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="eac-r11unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="eac-r11unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="eac-r11unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="eac-r11snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="eac-r11snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="eac-r11snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";aspect="all"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";aspect="all"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb";aspect="stencil-only"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginRenderPass:occlusion_query_set,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginComputePass:timestamp_query_set,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:cube_faces_square:*]
+ [:dimension="2d";size=[4,4,6\]]
+ expected: FAIL
+
+ [:dimension="2d";size=[5,5,6\]]
+ expected: FAIL
+
+ [:dimension="2d";size=[4,5,6\]]
+ expected: FAIL
+
+ [:dimension="2d";size=[4,8,6\]]
+ expected: FAIL
+
+ [:dimension="2d";size=[8,4,6\]]
+ expected: FAIL
+
+ [:dimension="cube";size=[4,4,6\]]
+ expected: FAIL
+
+ [:dimension="cube";size=[5,5,6\]]
+ expected: FAIL
+
+ [:dimension="cube";size=[4,5,6\]]
+ expected: FAIL
+
+ [:dimension="cube";size=[4,8,6\]]
+ expected: FAIL
+
+ [:dimension="cube";size=[8,4,6\]]
+ expected: FAIL
+
+ [:dimension="cube-array";size=[4,4,6\]]
+ expected: FAIL
+
+ [:dimension="cube-array";size=[5,5,6\]]
+ expected: FAIL
+
+ [:dimension="cube-array";size=[4,5,6\]]
+ expected: FAIL
+
+ [:dimension="cube-array";size=[4,8,6\]]
+ expected: FAIL
+
+ [:dimension="cube-array";size=[8,4,6\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:mip_levels:*]
+ [:textureDimension="1d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="1d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d-array"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube-array"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:viewFormats:*]
+ [:formatFeature="_undef_";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:formatFeature="_undef_";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-bc";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-bc";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-bc";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-bc";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-etc2";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-etc2";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-astc";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-astc";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-astc";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-astc";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-astc";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:formatFeature="_undef_";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:formatFeature="_undef_";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:formatFeature="_undef_";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:formatFeature="depth32float-stencil8";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:formatFeature="depth32float-stencil8";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:formatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:formatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:formatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:formatFeature="texture-compression-bc";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createTexture:texture_usage:*]
+ [:dimension="_undef_";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="r32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="_undef_";format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:format:*]
+ [:textureFormatFeature="_undef_";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:textureFormatFeature="_undef_";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-bc";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-bc";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-bc";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-bc";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-bc";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-etc2";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-etc2";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-etc2";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-astc";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-astc";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-astc";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-astc";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:textureFormatFeature="texture-compression-astc";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:textureFormatFeature="_undef_";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:textureFormatFeature="_undef_";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:textureFormatFeature="_undef_";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:textureFormatFeature="depth32float-stencil8";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:textureFormatFeature="depth32float-stencil8";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:textureFormatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:textureFormatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:textureFormatFeature="depth32float-stencil8";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginRenderPass:depth_stencil_attachment,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:texture_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,query_set_type:*]
+ [:queryTypeA="occlusion";queryTypeB="occlusion"]
+ expected: FAIL
+
+ [:queryTypeA="occlusion";queryTypeB="timestamp"]
+ expected: FAIL
+
+ [:queryTypeA="timestamp";queryTypeB="occlusion"]
+ expected: FAIL
+
+ [:queryTypeA="timestamp";queryTypeB="timestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,invalid_query_set:*]
+ [:querySetState="valid"]
+ expected: FAIL
+
+ [:querySetState="invalid"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:dimension:*]
+ [:textureDimension="1d";viewDimension="1d"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="2d"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="2d-array"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="cube"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="cube-array"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="3d"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="1d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d-array"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube-array"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="3d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="1d"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="2d"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="2d-array"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="cube"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="cube-array"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="3d"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="_undef_"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,beginRenderPass:timestamp_query_set,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,createView:array_layers:*]
+ [:textureDimension="1d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="1d";viewDimension="1d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="2d-array"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube"]
+ expected: FAIL
+
+ [:textureDimension="2d";viewDimension="cube-array"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="_undef_"]
+ expected: FAIL
+
+ [:textureDimension="3d";viewDimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:*]
+ [:bufferState="valid"]
+ expected: FAIL
+
+ [:bufferState="invalid"]
+ expected: FAIL
+
+ [:bufferState="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:size_alignment:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/15/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/15/cts.https.html.ini
new file mode 100644
index 0000000000..29529efa43
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/15/cts.https.html.ini
@@ -0,0 +1,273 @@
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_within_same_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:mipmap_level:*]
+ [:dimension="1d"]
+ expected: FAIL
+
+ [:dimension="2d"]
+ expected: FAIL
+
+ [:dimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:depth_stencil_copy_restrictions:*]
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:sample_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer,usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_out_of_bounds:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_with_invalid_or_destroyed_texture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:overflow:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_state:*]
+ [:srcBufferState="valid";dstBufferState="valid"]
+ expected: FAIL
+
+ [:srcBufferState="valid";dstBufferState="invalid"]
+ expected: FAIL
+
+ [:srcBufferState="valid";dstBufferState="destroyed"]
+ expected: FAIL
+
+ [:srcBufferState="invalid";dstBufferState="valid"]
+ expected: FAIL
+
+ [:srcBufferState="invalid";dstBufferState="invalid"]
+ expected: FAIL
+
+ [:srcBufferState="invalid";dstBufferState="destroyed"]
+ expected: FAIL
+
+ [:srcBufferState="destroyed";dstBufferState="valid"]
+ expected: FAIL
+
+ [:srcBufferState="destroyed";dstBufferState="invalid"]
+ expected: FAIL
+
+ [:srcBufferState="destroyed";dstBufferState="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:set_pipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_format_compatibility:*]
+ [:srcFormatFeature="_undef_";dstFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:srcFormatFeature="_undef_";dstFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-bc";dstFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-bc";dstFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:srcFormatFeature="_undef_";dstFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:srcFormatFeature="_undef_";dstFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:srcFormatFeature="_undef_";dstFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:srcFormatFeature="depth32float-stencil8";dstFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:srcFormatFeature="depth32float-stencil8";dstFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:srcFormatFeature="depth32float-stencil8";dstFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:srcFormatFeature="depth32float-stencil8";dstFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:srcFormatFeature="depth32float-stencil8";dstFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-bc";dstFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-bc";dstFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-bc";dstFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-etc2";dstFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-etc2";dstFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-etc2";dstFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-etc2";dstFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-etc2";dstFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-astc";dstFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-astc";dstFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-astc";dstFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-astc";dstFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:srcFormatFeature="texture-compression-astc";dstFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:out_of_bounds:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:pipeline,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,clearBuffer:offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:dispatch_sizes:*]
+ [:dispatchType="direct";largeDimValue=0]
+ expected: FAIL
+
+ [:dispatchType="direct";largeDimValue=1]
+ expected: FAIL
+
+ [:dispatchType="direct";largeDimValue=65535]
+ expected: FAIL
+
+ [:dispatchType="direct";largeDimValue=65536]
+ expected: FAIL
+
+ [:dispatchType="direct";largeDimValue=2147483647]
+ expected: FAIL
+
+ [:dispatchType="direct";largeDimValue=4294967295]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=0]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=1]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=65535]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=65536]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=2147483647]
+ expected: FAIL
+
+ [:dispatchType="indirect";largeDimValue=4294967295]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_size_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:multisampled_copy_restrictions:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_overflow:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/16/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/16/cts.https.html.ini
new file mode 100644
index 0000000000..b9e353569e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/16/cts.https.html.ini
@@ -0,0 +1,6474 @@
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,x_y_width_height_nonnegative:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:*]
+ [:encoderType="non-pass"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds:*]
+ [:indexCount=6;firstIndex=0;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=6;firstIndex=0;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=6;firstIndex=1;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=6;firstIndex=1;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=6;firstIndex=10000;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=6;firstIndex=10000;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=5;firstIndex=1;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=5;firstIndex=1;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=1;firstIndex=5;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=1;firstIndex=5;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=1;firstIndex=6;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=1;firstIndex=6;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=6;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=6;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=7;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=7;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=7;firstIndex=0;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=7;firstIndex=0;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=10000;firstIndex=0;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=10000;firstIndex=0;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=4294967295;firstIndex=4294967295;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=4294967295;firstIndex=4294967295;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=4294967295;firstIndex=2;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=4294967295;firstIndex=2;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=2;firstIndex=4294967295;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=2;firstIndex=4294967295;instanceCount=10000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setBlendConstant:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,xy_rect_contained_in_attachment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_aspects:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:index_buffer_OOB:*]
+ [:bufferSizeInElements=10;bindingSizeInElements=10;drawIndexCount=10;drawType="drawIndexed"]
+ expected: FAIL
+
+ [:bufferSizeInElements=10;bindingSizeInElements=10;drawIndexCount=10;drawType="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:bufferSizeInElements=10;bindingSizeInElements=10;drawIndexCount=11;drawType="drawIndexed"]
+ expected: FAIL
+
+ [:bufferSizeInElements=10;bindingSizeInElements=10;drawIndexCount=11;drawType="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:bufferSizeInElements=100;bindingSizeInElements=10;drawIndexCount=10;drawType="drawIndexed"]
+ expected: FAIL
+
+ [:bufferSizeInElements=100;bindingSizeInElements=10;drawIndexCount=10;drawType="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:bufferSizeInElements=100;bindingSizeInElements=10;drawIndexCount=11;drawType="drawIndexed"]
+ expected: FAIL
+
+ [:bufferSizeInElements=100;bindingSizeInElements=10;drawIndexCount=11;drawType="drawIndexedIndirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds_zero_sized_index_buffer:*]
+ [:indexCount=3;firstIndex=1;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=3;firstIndex=1;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=3;firstIndex=0;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=3;firstIndex=0;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=1;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=1;instanceCount=10000]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=0;instanceCount=1]
+ expected: FAIL
+
+ [:indexCount=0;firstIndex=0;instanceCount=10000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:*]
+ [:format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11snorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11snorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,x_y_width_height_nonnegative:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:buffer_binding_overlap:*]
+ [:drawType="draw"]
+ expected: FAIL
+
+ [:drawType="drawIndexed"]
+ expected: FAIL
+
+ [:drawType="drawIndirect"]
+ expected: FAIL
+
+ [:drawType="drawIndexedIndirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges:*]
+ [:dimension="1d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="2d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":1,"y":0,"z":0,"width":-1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":1,"z":0,"width":0,"height":-1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":1,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":1,"height":0,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":1,"depthOrArrayLayers":-2};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":0,"width":0,"height":0,"depthOrArrayLayers":0};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":1,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=0;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=1;dstCopyLevel=3]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=0]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=1]
+ expected: FAIL
+
+ [:dimension="3d";copyBoxOffsets={"x":0,"y":0,"z":2,"width":0,"height":0,"depthOrArrayLayers":-1};srcCopyLevel=3;dstCopyLevel=3]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:max_draw_count:*]
+ [:bundleFirstHalf=false;bundleSecondHalf=false;maxDrawCount=0]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=false;maxDrawCount=1]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=false;maxDrawCount=4]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=false;maxDrawCount=16]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=true;maxDrawCount=0]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=true;maxDrawCount=1]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=true;maxDrawCount=4]
+ expected: FAIL
+
+ [:bundleFirstHalf=false;bundleSecondHalf=true;maxDrawCount=16]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=false;maxDrawCount=0]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=false;maxDrawCount=1]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=false;maxDrawCount=4]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=false;maxDrawCount=16]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=true;maxDrawCount=0]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=true;maxDrawCount=1]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=true;maxDrawCount=4]
+ expected: FAIL
+
+ [:bundleFirstHalf=true;bundleSecondHalf=true;maxDrawCount=16]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:unused_buffer_bound:*]
+ [:smallIndexBuffer=false;smallVertexBuffer=false;smallInstanceBuffer=false]
+ expected: FAIL
+
+ [:smallIndexBuffer=false;smallVertexBuffer=false;smallInstanceBuffer=true]
+ expected: FAIL
+
+ [:smallIndexBuffer=false;smallVertexBuffer=true;smallInstanceBuffer=false]
+ expected: FAIL
+
+ [:smallIndexBuffer=false;smallVertexBuffer=true;smallInstanceBuffer=true]
+ expected: FAIL
+
+ [:smallIndexBuffer=true;smallVertexBuffer=false;smallInstanceBuffer=false]
+ expected: FAIL
+
+ [:smallIndexBuffer=true;smallVertexBuffer=false;smallInstanceBuffer=true]
+ expected: FAIL
+
+ [:smallIndexBuffer=true;smallVertexBuffer=true;smallInstanceBuffer=false]
+ expected: FAIL
+
+ [:smallIndexBuffer=true;smallVertexBuffer=true;smallInstanceBuffer=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,debug:debug_marker:*]
+ [:encoderType="non-pass"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_within_same_texture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setStencilReference:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:last_buffer_setting_take_account:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,draw:vertex_buffer_OOB:*]
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="draw";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexed";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="zero";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="exile";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="zero";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="exile";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=false;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=false;AStride="oversize";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="zero";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="exact";offset=7]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=0]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=1]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=2]
+ expected: FAIL
+
+ [:type="drawIndexedIndirect";VBSize="enough";IBSize="enough";VStride0=true;IStride0=true;AStride="oversize";offset=7]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,depth_rangeAndOrder:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,debug:debug_group:*]
+ [:encoderType="non-pass"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,xy_rect_contained_in_attachment:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/17/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/17/cts.https.html.ini
new file mode 100644
index 0000000000..5c71ac3956
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/17/cts.https.html.ini
@@ -0,0 +1,405 @@
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_and_size_oob:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_oob:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_passed_but_not_expected:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:state_and_binding_index:*]
+ [:encoderType="compute%20pass";state="valid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";state="valid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";state="invalid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";state="invalid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";state="destroyed";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";state="destroyed";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="valid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="valid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="invalid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="invalid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="destroyed";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";state="destroyed";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="valid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="valid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="invalid";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="invalid";resourceType="texture"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="destroyed";resourceType="buffer"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";state="destroyed";resourceType="texture"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_vertex_buffer_should_be_bound:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_index_buffer_should_be_bound:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_and_size_oob:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:u32array_start_and_length:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setPipeline:pipeline,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_do_not_inherit_between_render_passes:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setPipeline:invalid_pipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:slot:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_inherit_from_previous_pipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:*]
+ [:type="uniform";encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:type="uniform";encoderType="render%20pass"]
+ expected: FAIL
+
+ [:type="uniform";encoderType="render%20bundle"]
+ expected: FAIL
+
+ [:type="storage";encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:type="storage";encoderType="render%20pass"]
+ expected: FAIL
+
+ [:type="storage";encoderType="render%20bundle"]
+ expected: FAIL
+
+ [:type="read-only-storage";encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:type="read-only-storage";encoderType="render%20pass"]
+ expected: FAIL
+
+ [:type="read-only-storage";encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_match_expectations_in_pass_encoder:*]
+ [:encoderType="compute%20pass";dynamicOffsets=[256,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[256,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[1,2\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[1,2\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[256,0,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[256,0,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[256\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[256\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[512,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[512,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[1024,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[1024,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[4294967295,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[4294967295,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,512\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,512\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,1024\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,1024\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,4294967295\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";dynamicOffsets=[0,4294967295\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[1,2\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[1,2\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256,0,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256,0,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[256\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[512,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[512,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[1024,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[1024,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[4294967295,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[4294967295,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,512\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,512\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,1024\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,1024\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,4294967295\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";dynamicOffsets=[0,4294967295\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[1,2\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[1,2\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256,0,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256,0,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[256\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[512,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[512,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[1024,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[1024,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[4294967295,0\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[4294967295,0\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,512\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,512\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,1024\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,1024\];useU32array=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,4294967295\];useU32array=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";dynamicOffsets=[0,4294967295\];useU32array=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,cmds,setBindGroup:bind_group,device_mismatch:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/18/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/18/cts.https.html.ini
new file mode 100644
index 0000000000..45256e348e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/18/cts.https.html.ini
@@ -0,0 +1,945 @@
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:buffer_binding,render_pipeline:*]
+ [:type="uniform"]
+ expected: FAIL
+
+ [:type="storage"]
+ expected: FAIL
+
+ [:type="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,compute_pass:*]
+ [:bindGroupLayoutEntryCount=3;computeCommand="dispatchIndirect"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=3;computeCommand="dispatch"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;computeCommand="dispatchIndirect"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;computeCommand="dispatch"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachments:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_balance:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_visibility_mismatch:*]
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachmentBytesPerSample,aligned:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bind_groups_and_pipeline_layout_mismatch:*]
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:sampler_binding,render_pipeline:*]
+ [:bglType="filtering";bgType="filtering"]
+ expected: FAIL
+
+ [:bglType="filtering";bgType="non-filtering"]
+ expected: FAIL
+
+ [:bglType="filtering";bgType="comparison"]
+ expected: FAIL
+
+ [:bglType="non-filtering";bgType="filtering"]
+ expected: FAIL
+
+ [:bglType="non-filtering";bgType="non-filtering"]
+ expected: FAIL
+
+ [:bglType="non-filtering";bgType="comparison"]
+ expected: FAIL
+
+ [:bglType="comparison";bgType="filtering"]
+ expected: FAIL
+
+ [:bglType="comparison";bgType="non-filtering"]
+ expected: FAIL
+
+ [:bglType="comparison";bgType="comparison"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_state:call_after_successful_finish:*]
+ [:callCmd="beginComputePass"]
+ expected: FAIL
+
+ [:callCmd="beginRenderPass"]
+ expected: FAIL
+
+ [:callCmd="insertDebugMarker"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,render_pass:*]
+ [:bindGroupLayoutEntryCount=3;renderCommand="draw"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=3;renderCommand="drawIndexed"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=3;renderCommand="drawIndirect"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=3;renderCommand="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;renderCommand="draw"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;renderCommand="drawIndexed"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;renderCommand="drawIndirect"]
+ expected: FAIL
+
+ [:bindGroupLayoutEntryCount=4;renderCommand="drawIndexedIndirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_open_state:render_bundle_commands:*]
+ [:command="draw"]
+ expected: FAIL
+
+ [:command="drawIndexed"]
+ expected: FAIL
+
+ [:command="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:command="drawIndirect"]
+ expected: FAIL
+
+ [:command="setPipeline"]
+ expected: FAIL
+
+ [:command="setBindGroup"]
+ expected: FAIL
+
+ [:command="setIndexBuffer"]
+ expected: FAIL
+
+ [:command="setVertexBuffer"]
+ expected: FAIL
+
+ [:command="pushDebugGroup"]
+ expected: FAIL
+
+ [:command="popDebugGroup"]
+ expected: FAIL
+
+ [:command="insertDebugMarker"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_state:pass_end_invalid_order:*]
+ [:pass0Type="compute";pass1Type="compute"]
+ expected: FAIL
+
+ [:pass0Type="compute";pass1Type="render"]
+ expected: FAIL
+
+ [:pass0Type="render";pass1Type="compute"]
+ expected: FAIL
+
+ [:pass0Type="render";pass1Type="render"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly_with_undefined_depth:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_resource_type_mismatch:*]
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_binding_mismatch:*]
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatch";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="compute%20pass";call="dispatchIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20pass";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="draw";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexed";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndirect";callWithZero=false]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=true]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";call="drawIndexedIndirect";callWithZero=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_state:pass_end_twice:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachmentBytesPerSample,unaligned:*]
+ [:formats=["r8unorm","r32float","rgba8unorm","rgba32float","r8unorm"\]]
+ expected: FAIL
+
+ [:formats=["r32float","rgba8unorm","rgba32float","r8unorm","r8unorm"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_open_state:render_pass_commands:*]
+ [:command="draw"]
+ expected: FAIL
+
+ [:command="drawIndexed"]
+ expected: FAIL
+
+ [:command="drawIndexedIndirect"]
+ expected: FAIL
+
+ [:command="drawIndirect"]
+ expected: FAIL
+
+ [:command="setIndexBuffer"]
+ expected: FAIL
+
+ [:command="setBindGroup"]
+ expected: FAIL
+
+ [:command="setVertexBuffer"]
+ expected: FAIL
+
+ [:command="setPipeline"]
+ expected: FAIL
+
+ [:command="setViewport"]
+ expected: FAIL
+
+ [:command="setScissorRect"]
+ expected: FAIL
+
+ [:command="setBlendConstant"]
+ expected: FAIL
+
+ [:command="setStencilReference"]
+ expected: FAIL
+
+ [:command="beginOcclusionQuery"]
+ expected: FAIL
+
+ [:command="endOcclusionQuery"]
+ expected: FAIL
+
+ [:command="executeBundles"]
+ expected: FAIL
+
+ [:command="pushDebugGroup"]
+ expected: FAIL
+
+ [:command="popDebugGroup"]
+ expected: FAIL
+
+ [:command="insertDebugMarker"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_open_state:compute_pass_commands:*]
+ [:command="setBindGroup"]
+ expected: FAIL
+
+ [:command="setPipeline"]
+ expected: FAIL
+
+ [:command="dispatchWorkgroups"]
+ expected: FAIL
+
+ [:command="dispatchWorkgroupsIndirect"]
+ expected: FAIL
+
+ [:command="pushDebugGroup"]
+ expected: FAIL
+
+ [:command="popDebugGroup"]
+ expected: FAIL
+
+ [:command="insertDebugMarker"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_state:pass_end_none:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,empty_color_formats:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,encoder_open_state:non_pass_commands:*]
+ [:command="beginComputePass"]
+ expected: FAIL
+
+ [:command="beginRenderPass"]
+ expected: FAIL
+
+ [:command="clearBuffer"]
+ expected: FAIL
+
+ [:command="copyBufferToBuffer"]
+ expected: FAIL
+
+ [:command="copyBufferToTexture"]
+ expected: FAIL
+
+ [:command="copyTextureToBuffer"]
+ expected: FAIL
+
+ [:command="copyTextureToTexture"]
+ expected: FAIL
+
+ [:command="insertDebugMarker"]
+ expected: FAIL
+
+ [:command="popDebugGroup"]
+ expected: FAIL
+
+ [:command="pushDebugGroup"]
+ expected: FAIL
+
+ [:command="resolveQuerySet"]
+ expected: FAIL
+
+ [:command="writeTimestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:valid_texture_formats:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="eac-r11unorm"]
+ expected: FAIL
+
+ [:format="eac-r11snorm"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly:*]
+ [:depthStencilFormat="depth32float"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth16unorm"]
+ expected: FAIL
+
+ [:depthStencilFormat="stencil8"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth24plus"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_invalid_nesting:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/19/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/19/cts.https.html.ini
new file mode 100644
index 0000000000..6d2eb21798
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/19/cts.https.html.ini
@@ -0,0 +1,297 @@
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:occlusion_query,invalid_query_set:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:timestamp_query,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:sample_count_mismatch:*]
+ [:bundleSamples=1;passSamples=1]
+ expected: FAIL
+
+ [:bundleSamples=4;passSamples=4]
+ expected: FAIL
+
+ [:bundleFormat=4;passFormat=1]
+ expected: FAIL
+
+ [:bundleFormat=1;passFormat=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:timestamp_query,invalid_query_set:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:empty_bundle_list:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,begin_end:nesting:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:simple:*]
+ [:errorType="out-of-memory";errorFilter="out-of-memory"]
+ expected: FAIL
+
+ [:errorType="out-of-memory";errorFilter="validation"]
+ expected: FAIL
+
+ [:errorType="out-of-memory";errorFilter="internal"]
+ expected: FAIL
+
+ [:errorType="validation";errorFilter="out-of-memory"]
+ expected: FAIL
+
+ [:errorType="validation";errorFilter="internal"]
+ expected: FAIL
+
+ [:errorType="validation";errorFilter="validation"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_offset_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:parent_scope:*]
+ [:errorFilter="out-of-memory";stackDepth=1]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=10]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=100]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=1000]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=1]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=10]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=100]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=1000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:timestamp_query,query_type_and_index:*]
+ [:type="occlusion"]
+ expected: FAIL
+
+ [:type="timestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_formats_mismatch:*]
+ [:bundleFormat="depth24plus";passFormat="depth24plus"]
+ expected: FAIL
+
+ [:bundleFormat="depth24plus";passFormat="depth16unorm"]
+ expected: FAIL
+
+ [:bundleFormat="depth24plus";passFormat="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:bundleFormat="stencil8";passFormat="depth24plus-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:empty:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_readonly_mismatch:*]
+ [:depthStencilFormat="depth32float"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth16unorm"]
+ expected: FAIL
+
+ [:depthStencilFormat="stencil8"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth24plus"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_type:*]
+ [:type="_undef_"]
+ expected: FAIL
+
+ [:type="occlusion"]
+ expected: FAIL
+
+ [:type="timestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:current_scope:*]
+ [:errorFilter="out-of-memory";stackDepth=1]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=10]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=100]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=1000]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";stackDepth=100000]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=1]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=10]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=100]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=1000]
+ expected: FAIL
+
+ [:errorFilter="validation";stackDepth=100000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:balanced_siblings:*]
+ [:errorFilter="out-of-memory";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=1000]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=1000]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=1000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,disjoint_queries_with_same_query_index:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_buffer_usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,render_bundle:color_formats_mismatch:*]
+ [:bundleFormats=["bgra8unorm","rg8unorm"\];passFormats=["bgra8unorm","rg8unorm"\]]
+ expected: FAIL
+
+ [:bundleFormats=["bgra8unorm","rg8unorm"\];passFormats=["bgra8unorm","bgra8unorm"\]]
+ expected: FAIL
+
+ [:bundleFormats=["bgra8unorm","rg8unorm"\];passFormats=["rg8unorm","bgra8unorm"\]]
+ expected: FAIL
+
+ [:bundleFormats=["bgra8unorm","rg8unorm"\];passFormats=["rg8unorm","bgra8unorm","rgba8unorm"\]]
+ expected: FAIL
+
+ [:bundleFormats=["bgra8unorm","rg8unorm","rgba8unorm"\];passFormats=["rg8unorm","bgra8unorm"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:queryset_and_destination_buffer_state:*]
+ [:querySetState="valid";destinationState="valid"]
+ expected: FAIL
+
+ [:querySetState="valid";destinationState="invalid"]
+ expected: FAIL
+
+ [:querySetState="valid";destinationState="destroyed"]
+ expected: FAIL
+
+ [:querySetState="invalid";destinationState="valid"]
+ expected: FAIL
+
+ [:querySetState="invalid";destinationState="invalid"]
+ expected: FAIL
+
+ [:querySetState="invalid";destinationState="destroyed"]
+ expected: FAIL
+
+ [:querySetState="destroyed";destinationState="valid"]
+ expected: FAIL
+
+ [:querySetState="destroyed";destinationState="invalid"]
+ expected: FAIL
+
+ [:querySetState="destroyed";destinationState="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:resolve_buffer_oob:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_index:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:query_set_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,encoding,queries,resolveQuerySet:first_query_and_query_count:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/2/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/2/cts.https.html.ini
new file mode 100644
index 0000000000..b2bd2331df
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/2/cts.https.html.ini
@@ -0,0 +1,5925 @@
+[cts.https.html?q=webgpu:api,operation,command_buffer,basic:empty:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:*]
+ [:srcFormat="bc1-rgba-unorm";dstFormat="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm";dstFormat="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm-srgb";dstFormat="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm-srgb";dstFormat="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm";dstFormat="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm";dstFormat="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm-srgb";dstFormat="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm-srgb";dstFormat="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm";dstFormat="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm";dstFormat="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm-srgb";dstFormat="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm-srgb";dstFormat="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc4-r-unorm";dstFormat="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc4-r-snorm";dstFormat="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc5-rg-unorm";dstFormat="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc5-rg-snorm";dstFormat="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc6h-rgb-ufloat";dstFormat="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc6h-rgb-float";dstFormat="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm";dstFormat="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm";dstFormat="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm-srgb";dstFormat="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm-srgb";dstFormat="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm";dstFormat="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm";dstFormat="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm-srgb";dstFormat="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm-srgb";dstFormat="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm";dstFormat="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm";dstFormat="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm-srgb";dstFormat="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm-srgb";dstFormat="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm";dstFormat="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm";dstFormat="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm-srgb";dstFormat="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm-srgb";dstFormat="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-r11unorm";dstFormat="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-r11snorm";dstFormat="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-rg11unorm";dstFormat="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-rg11snorm";dstFormat="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm";dstFormat="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm";dstFormat="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm-srgb";dstFormat="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm-srgb";dstFormat="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm";dstFormat="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm";dstFormat="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm-srgb";dstFormat="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm-srgb";dstFormat="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm";dstFormat="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm";dstFormat="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm-srgb";dstFormat="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm-srgb";dstFormat="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm";dstFormat="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm";dstFormat="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm-srgb";dstFormat="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm-srgb";dstFormat="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm";dstFormat="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm";dstFormat="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm-srgb";dstFormat="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm-srgb";dstFormat="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm";dstFormat="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm";dstFormat="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm-srgb";dstFormat="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm-srgb";dstFormat="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm";dstFormat="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm";dstFormat="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm-srgb";dstFormat="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm-srgb";dstFormat="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm";dstFormat="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm";dstFormat="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm-srgb";dstFormat="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm-srgb";dstFormat="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm";dstFormat="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm";dstFormat="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm-srgb";dstFormat="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm-srgb";dstFormat="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm";dstFormat="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm";dstFormat="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm-srgb";dstFormat="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm-srgb";dstFormat="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm";dstFormat="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm";dstFormat="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm-srgb";dstFormat="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm-srgb";dstFormat="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm";dstFormat="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm";dstFormat="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm-srgb";dstFormat="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm-srgb";dstFormat="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm";dstFormat="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm";dstFormat="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm-srgb";dstFormat="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm-srgb";dstFormat="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm";dstFormat="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm";dstFormat="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm-srgb";dstFormat="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm-srgb";dstFormat="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:*]
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_color:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:copy_order:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,buffers,threading:destroyed:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:state_transitions:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:*]
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:undefined_params:*]
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";dimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow_depth_stencil:*]
+ [:format="depth32float";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth16unorm";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_depth:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:single:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_indices:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes_copy_depth_stencil:*]
+ [:format="depth32float";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth16unorm";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="WriteTexture";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyB2T";aspect="stencil-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyT2B";aspect="depth-only"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";copyMethod="CopyT2B";aspect="stencil-only"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:*]
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:*]
+ [:srcFormat="bc1-rgba-unorm";dstFormat="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm";dstFormat="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm-srgb";dstFormat="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc1-rgba-unorm-srgb";dstFormat="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm";dstFormat="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm";dstFormat="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm-srgb";dstFormat="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc2-rgba-unorm-srgb";dstFormat="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm";dstFormat="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm";dstFormat="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm-srgb";dstFormat="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc3-rgba-unorm-srgb";dstFormat="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc4-r-unorm";dstFormat="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc4-r-snorm";dstFormat="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc5-rg-unorm";dstFormat="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc5-rg-snorm";dstFormat="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc6h-rgb-ufloat";dstFormat="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc6h-rgb-float";dstFormat="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm";dstFormat="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm";dstFormat="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm-srgb";dstFormat="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bc7-rgba-unorm-srgb";dstFormat="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm";dstFormat="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm";dstFormat="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm-srgb";dstFormat="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8unorm-srgb";dstFormat="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm";dstFormat="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm";dstFormat="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm-srgb";dstFormat="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgb8a1unorm-srgb";dstFormat="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm";dstFormat="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm";dstFormat="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm-srgb";dstFormat="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="etc2-rgba8unorm-srgb";dstFormat="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-r11unorm";dstFormat="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-r11snorm";dstFormat="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-rg11unorm";dstFormat="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="eac-rg11snorm";dstFormat="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm";dstFormat="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm";dstFormat="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm-srgb";dstFormat="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-4x4-unorm-srgb";dstFormat="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm";dstFormat="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm";dstFormat="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm-srgb";dstFormat="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x4-unorm-srgb";dstFormat="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm";dstFormat="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm";dstFormat="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm-srgb";dstFormat="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-5x5-unorm-srgb";dstFormat="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm";dstFormat="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm";dstFormat="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm-srgb";dstFormat="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x5-unorm-srgb";dstFormat="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm";dstFormat="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm";dstFormat="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm-srgb";dstFormat="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-6x6-unorm-srgb";dstFormat="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm";dstFormat="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm";dstFormat="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm-srgb";dstFormat="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x5-unorm-srgb";dstFormat="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm";dstFormat="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm";dstFormat="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm-srgb";dstFormat="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x6-unorm-srgb";dstFormat="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm";dstFormat="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm";dstFormat="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm-srgb";dstFormat="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-8x8-unorm-srgb";dstFormat="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm";dstFormat="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm";dstFormat="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm-srgb";dstFormat="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x5-unorm-srgb";dstFormat="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm";dstFormat="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm";dstFormat="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm-srgb";dstFormat="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x6-unorm-srgb";dstFormat="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm";dstFormat="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm";dstFormat="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm-srgb";dstFormat="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x8-unorm-srgb";dstFormat="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm";dstFormat="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm";dstFormat="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm-srgb";dstFormat="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-10x10-unorm-srgb";dstFormat="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm";dstFormat="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm";dstFormat="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm-srgb";dstFormat="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x10-unorm-srgb";dstFormat="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm";dstFormat="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm";dstFormat="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm-srgb";dstFormat="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="astc-12x12-unorm-srgb";dstFormat="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:*]
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:zero_sized:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:*]
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,basic:b2t2t2b:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:*]
+ [:srcFormat="r8unorm";dstFormat="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r8unorm";dstFormat="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8unorm";dstFormat="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8snorm";dstFormat="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r8snorm";dstFormat="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8snorm";dstFormat="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8uint";dstFormat="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r8uint";dstFormat="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8uint";dstFormat="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8sint";dstFormat="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r8sint";dstFormat="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8sint";dstFormat="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16uint";dstFormat="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r16uint";dstFormat="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16uint";dstFormat="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16sint";dstFormat="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r16sint";dstFormat="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16sint";dstFormat="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16float";dstFormat="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r16float";dstFormat="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16float";dstFormat="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8unorm";dstFormat="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg8unorm";dstFormat="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8unorm";dstFormat="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8snorm";dstFormat="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg8snorm";dstFormat="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8snorm";dstFormat="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8uint";dstFormat="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg8uint";dstFormat="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8uint";dstFormat="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8sint";dstFormat="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg8sint";dstFormat="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8sint";dstFormat="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32uint";dstFormat="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r32uint";dstFormat="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32uint";dstFormat="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32sint";dstFormat="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r32sint";dstFormat="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32sint";dstFormat="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32float";dstFormat="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="r32float";dstFormat="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32float";dstFormat="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16uint";dstFormat="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg16uint";dstFormat="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16uint";dstFormat="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16sint";dstFormat="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg16sint";dstFormat="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16sint";dstFormat="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16float";dstFormat="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg16float";dstFormat="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16float";dstFormat="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8snorm";dstFormat="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8snorm";dstFormat="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8snorm";dstFormat="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8uint";dstFormat="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8uint";dstFormat="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8uint";dstFormat="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8sint";dstFormat="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8sint";dstFormat="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8sint";dstFormat="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgb10a2unorm";dstFormat="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgb10a2unorm";dstFormat="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgb10a2unorm";dstFormat="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg11b10ufloat";dstFormat="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg11b10ufloat";dstFormat="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg11b10ufloat";dstFormat="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgb9e5ufloat";dstFormat="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgb9e5ufloat";dstFormat="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgb9e5ufloat";dstFormat="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32uint";dstFormat="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg32uint";dstFormat="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32uint";dstFormat="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32sint";dstFormat="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg32sint";dstFormat="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32sint";dstFormat="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32float";dstFormat="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rg32float";dstFormat="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32float";dstFormat="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16uint";dstFormat="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16uint";dstFormat="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16uint";dstFormat="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16sint";dstFormat="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16sint";dstFormat="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16sint";dstFormat="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16float";dstFormat="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16float";dstFormat="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16float";dstFormat="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32uint";dstFormat="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32uint";dstFormat="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32uint";dstFormat="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32sint";dstFormat="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32sint";dstFormat="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32sint";dstFormat="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32float";dstFormat="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32float";dstFormat="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32float";dstFormat="rgba32float";dimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,clearBuffer:clear:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,basic:b2t2b:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:*]
+ [:srcFormat="r8unorm";dstFormat="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8unorm";dstFormat="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8snorm";dstFormat="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8snorm";dstFormat="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8uint";dstFormat="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8uint";dstFormat="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r8sint";dstFormat="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r8sint";dstFormat="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16uint";dstFormat="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16uint";dstFormat="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16sint";dstFormat="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16sint";dstFormat="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r16float";dstFormat="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r16float";dstFormat="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8unorm";dstFormat="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8unorm";dstFormat="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8snorm";dstFormat="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8snorm";dstFormat="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8uint";dstFormat="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8uint";dstFormat="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg8sint";dstFormat="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg8sint";dstFormat="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32uint";dstFormat="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32uint";dstFormat="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32sint";dstFormat="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32sint";dstFormat="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="r32float";dstFormat="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="r32float";dstFormat="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16uint";dstFormat="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16uint";dstFormat="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16sint";dstFormat="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16sint";dstFormat="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg16float";dstFormat="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg16float";dstFormat="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm";dstFormat="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8unorm-srgb";dstFormat="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8snorm";dstFormat="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8snorm";dstFormat="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8uint";dstFormat="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8uint";dstFormat="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8sint";dstFormat="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba8sint";dstFormat="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm";dstFormat="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="bgra8unorm-srgb";dstFormat="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgb10a2unorm";dstFormat="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgb10a2unorm";dstFormat="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg11b10ufloat";dstFormat="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg11b10ufloat";dstFormat="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgb9e5ufloat";dstFormat="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgb9e5ufloat";dstFormat="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32uint";dstFormat="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32uint";dstFormat="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32sint";dstFormat="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32sint";dstFormat="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rg32float";dstFormat="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rg32float";dstFormat="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16uint";dstFormat="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16uint";dstFormat="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16sint";dstFormat="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16sint";dstFormat="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16float";dstFormat="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba16float";dstFormat="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32uint";dstFormat="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32uint";dstFormat="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32sint";dstFormat="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32sint";dstFormat="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32float";dstFormat="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:srcFormat="rgba32float";dstFormat="rgba32float";dimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_order:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/20/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/20/cts.https.html.ini
new file mode 100644
index 0000000000..a5b8914cb9
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/20/cts.https.html.ini
@@ -0,0 +1,7779 @@
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:texture_buffer_usages:*]
+ [:copyType="CopyB2T"]
+ expected: FAIL
+
+ [:copyType="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,getBindGroupLayout:index_range,explicit_layout:*]
+ [:index=0]
+ expected: FAIL
+
+ [:index=1]
+ expected: FAIL
+
+ [:index=2]
+ expected: FAIL
+
+ [:index=3]
+ expected: FAIL
+
+ [:index=4]
+ expected: FAIL
+
+ [:index=5]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_related:buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_related:bytes_per_row_alignment:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,getBindGroupLayout:unique_js_object,explicit_layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:bound_on_rows_per_image:*]
+ [: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
+
+ [:method="CopyB2T";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="3d";size=[4,4,3\]]
+ 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
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_usage_and_aspect:*]
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_buffer_size:*]
+ [:format="depth32float";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:texture,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:offset_alignment:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,error_scope:balanced_nesting:*]
+ [:errorFilter="out-of-memory";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="out-of-memory";numErrors=1000]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="validation";numErrors=1000]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=1]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=10]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=100]
+ expected: FAIL
+
+ [:errorFilter="internal";numErrors=1000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_related:usage:*]
+ [:method="CopyB2T"]
+ expected: FAIL
+
+ [:method="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:bound_on_bytes_per_row:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:rows_per_image_alignment:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:copy_end_overflows_u64:*]
+ [:method="WriteTexture"]
+ expected: FAIL
+
+ [:method="CopyB2T"]
+ expected: FAIL
+
+ [:method="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="depth16unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="stencil8";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:device_mismatch:*]
+ [:copyType="CopyB2T"]
+ expected: FAIL
+
+ [:copyType="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_buffer_offset:*]
+ [:format="depth32float";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth16unorm";aspect="depth-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="depth-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="CopyB2T"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="CopyT2B"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";aspect="stencil-only";copyType="WriteTexture"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,getBindGroupLayout:unique_js_object,auto_layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_texture_copies:sample_count:*]
+ [:copyType="CopyB2T"]
+ expected: FAIL
+
+ [:copyType="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:usage:*]
+ [: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
+
+ [:method="CopyB2T";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="3d";size=[4,4,3\]]
+ 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
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,layout_related:bound_on_offset:*]
+ [:method="WriteTexture"]
+ expected: FAIL
+
+ [:method="CopyB2T"]
+ expected: FAIL
+
+ [:method="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:valid:*]
+ [:method="WriteTexture";textureState="valid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="valid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="valid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="valid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="invalid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="invalid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="invalid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="invalid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="destroyed";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="destroyed";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="destroyed";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";textureState="destroyed";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="valid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="valid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="valid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="valid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="invalid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="invalid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="invalid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="invalid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="destroyed";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="destroyed";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="destroyed";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";textureState="destroyed";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="valid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="valid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="valid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="valid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="invalid";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="invalid";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="invalid";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="invalid";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="destroyed";dimension="1d";size=[4,1,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="destroyed";dimension="2d";size=[4,4,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="destroyed";dimension="2d";size=[4,4,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";textureState="destroyed";dimension="3d";size=[4,4,3\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,buffer_related:buffer_state:*]
+ [:method="CopyB2T";state="valid"]
+ expected: FAIL
+
+ [:method="CopyB2T";state="invalid"]
+ expected: FAIL
+
+ [:method="CopyB2T";state="destroyed"]
+ expected: FAIL
+
+ [:method="CopyT2B";state="valid"]
+ expected: FAIL
+
+ [:method="CopyT2B";state="invalid"]
+ expected: FAIL
+
+ [:method="CopyT2B";state="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,getBindGroupLayout:index_range,auto_layout:*]
+ [:index=0]
+ expected: FAIL
+
+ [:index=1]
+ expected: FAIL
+
+ [:index=2]
+ expected: FAIL
+
+ [:index=3]
+ expected: FAIL
+
+ [:index=4]
+ expected: FAIL
+
+ [:index=5]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/21/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/21/cts.https.html.ini
new file mode 100644
index 0000000000..b6c763dd37
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/21/cts.https.html.ini
@@ -0,0 +1,6492 @@
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:copy_rectangle:*]
+ [:method="WriteTexture";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="3d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,contexts:*]
+ [:contextType="2d"]
+ expected: FAIL
+
+ [:contextType="bitmaprenderer"]
+ expected: FAIL
+
+ [:contextType="webgl"]
+ expected: FAIL
+
+ [:contextType="webgl2"]
+ expected: FAIL
+
+ [:contextType="webgpu"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,format:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="eac-r11unorm"]
+ expected: FAIL
+
+ [:format="eac-r11snorm"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,mipLevel:*]
+ [:mipLevel=0]
+ expected: FAIL
+
+ [:mipLevel=5]
+ expected: FAIL
+
+ [:mipLevel=6]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:mip_level:*]
+ [:method="WriteTexture";dimension="1d";size=[32,1,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";dimension="2d";size=[32,32,1\]]
+ expected: FAIL
+
+ [:method="WriteTexture";dimension="2d";size=[32,32,3\]]
+ expected: FAIL
+
+ [:method="WriteTexture";dimension="3d";size=[32,32,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="1d";size=[32,1,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[32,32,1\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="2d";size=[32,32,3\]]
+ expected: FAIL
+
+ [:method="CopyB2T";dimension="3d";size=[32,32,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="1d";size=[32,1,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="2d";size=[32,32,1\]]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="2d";size=[32,32,3\]]
+ expected: FAIL
+
+ [:method="CopyT2B";dimension="3d";size=[32,32,3\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,contexts:*]
+ [:contextType="2d"]
+ expected: FAIL
+
+ [:contextType="bitmaprenderer"]
+ expected: FAIL
+
+ [:contextType="webgl"]
+ expected: FAIL
+
+ [:contextType="webgl2"]
+ expected: FAIL
+
+ [:contextType="webgpu"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:format:*]
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyB2T";depthOrArrayLayers=32;dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="1d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=1;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="rgba32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="depth32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="depth16unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="stencil8"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="eac-r11unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="eac-r11snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=3;dimension="2d";format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="r32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba8snorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba8uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba8sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rg32float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba16uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba16sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba16float"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba32uint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba32sint"]
+ expected: FAIL
+
+ [:method="CopyT2B";depthOrArrayLayers=32;dimension="3d";format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,buffer_mapped:map_command_recording_order:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToTexture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,state:*]
+ [:state="nocontext"]
+ expected: FAIL
+
+ [:state="detached-nocontext"]
+ expected: FAIL
+
+ [:state="detached-hascontext"]
+ expected: FAIL
+
+ [:state="valid"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:size_alignment:*]
+ [:method="WriteTexture";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,query_set,destroy:twice:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,query_set,create:count:*]
+ [:type="occlusion"]
+ expected: FAIL
+
+ [:type="timestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,buffer_mapped:writeBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,state:*]
+ [:state="valid"]
+ expected: FAIL
+
+ [:state="invalid"]
+ expected: FAIL
+
+ [:state="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:*]
+ [:method="WriteTexture";format="r8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="r32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rg32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="rgba32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc4-r-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc5-rg-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc6h-rgb-float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-r11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="eac-rg11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-4x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-5x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-6x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-8x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-10x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="WriteTexture";format="astc-12x12-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="r32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rg32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="rgba32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc4-r-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc5-rg-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc6h-rgb-float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-r11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="eac-rg11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-4x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-5x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-6x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-8x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-10x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyB2T";format="astc-12x12-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="r32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8snorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba8sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bgra8unorm-srgb";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb10a2unorm";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg11b10ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgb9e5ufloat";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rg32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba16float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32uint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32sint";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";depthOrArrayLayers=1;dimension="1d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="rgba32float";depthOrArrayLayers=3;dimension="3d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc1-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc2-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc3-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc4-r-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc5-rg-snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-ufloat";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc6h-rgb-float";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="bc7-rgba-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgb8a1unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="etc2-rgba8unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-r11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="eac-rg11snorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-4x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x4-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-5x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-6x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-8x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x5-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x6-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x8-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-10x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x10-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";depthOrArrayLayers=1;dimension="2d"]
+ expected: FAIL
+
+ [:method="CopyT2B";format="astc-12x12-unorm-srgb";depthOrArrayLayers=3;dimension="2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,sample_count:*]
+ [:sampleCount=1]
+ expected: FAIL
+
+ [:sampleCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_imageBitmap,state:*]
+ [:closed=false]
+ expected: FAIL
+
+ [:closed=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,image_copy,texture_related:sample_count:*]
+ [:method="WriteTexture"]
+ expected: FAIL
+
+ [:method="CopyB2T"]
+ expected: FAIL
+
+ [:method="CopyT2B"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,state:*]
+ [:state="nocontext"]
+ expected: FAIL
+
+ [:state="placeholder-nocontext"]
+ expected: FAIL
+
+ [:state="placeholder-hascontext"]
+ expected: FAIL
+
+ [:state="valid"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_image,crossOrigin:*]
+ [:sourceImage="canvas";isOriginClean=true]
+ expected: FAIL
+
+ [:sourceImage="canvas";isOriginClean=false]
+ expected: FAIL
+
+ [:sourceImage="offscreenCanvas";isOriginClean=true]
+ expected: FAIL
+
+ [:sourceImage="offscreenCanvas";isOriginClean=false]
+ expected: FAIL
+
+ [:sourceImage="imageBitmap";isOriginClean=true]
+ expected: FAIL
+
+ [:sourceImage="imageBitmap";isOriginClean=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,buffer_mapped:copyTextureToBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,usage:*]
+ [:usage=1]
+ expected: FAIL
+
+ [:usage=2]
+ expected: FAIL
+
+ [:usage=4]
+ expected: FAIL
+
+ [:usage=8]
+ expected: FAIL
+
+ [:usage=16]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/22/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/22/cts.https.html.ini
new file mode 100644
index 0000000000..fa121778d3
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/22/cts.https.html.ini
@@ -0,0 +1,279 @@
+[cts.https.html?q=webgpu:api,validation,queue,writeTexture:texture,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeBuffer:usages:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_sparse:*]
+ [:encoderType="render%20pass";attachmentCount=1]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=2]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=3]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=4]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=5]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=6]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=7]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentCount=8]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=1]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=2]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=3]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=4]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=5]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=6]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=7]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentCount=8]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeBuffer:ranges:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,destroyed,query_set:resolveQuerySet:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_format:*]
+ [:encoderType="render%20pass";encoderFormatFeature="_undef_";pipelineFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";encoderFormatFeature="_undef_";pipelineFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";encoderFormatFeature="_undef_";pipelineFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";encoderFormatFeature="depth32float-stencil8";pipelineFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";encoderFormatFeature="depth32float-stencil8";pipelineFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";encoderFormatFeature="_undef_";pipelineFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";encoderFormatFeature="depth32float-stencil8";pipelineFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";encoderFormatFeature="depth32float-stencil8";pipelineFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_count:*]
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_format:*]
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeBuffer:buffer_state:*]
+ [:bufferState="valid"]
+ expected: FAIL
+
+ [:bufferState="invalid"]
+ expected: FAIL
+
+ [:bufferState="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,sample_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_sparse:*]
+ [:attachmentCount=1]
+ expected: FAIL
+
+ [:attachmentCount=2]
+ expected: FAIL
+
+ [:attachmentCount=3]
+ expected: FAIL
+
+ [:attachmentCount=4]
+ expected: FAIL
+
+ [:attachmentCount=5]
+ expected: FAIL
+
+ [:attachmentCount=6]
+ expected: FAIL
+
+ [:attachmentCount=7]
+ expected: FAIL
+
+ [:attachmentCount=8]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeTexture:texture_state:*]
+ [:textureState="valid"]
+ expected: FAIL
+
+ [:textureState="invalid"]
+ expected: FAIL
+
+ [:textureState="destroyed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,source:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeTexture:sample_count:*]
+ [:sampleCount=1]
+ expected: FAIL
+
+ [:sampleCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeBuffer:buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,writeTexture:usages:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,destroyed,query_set:beginOcclusionQuery:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,depth_format:*]
+ [:passFeature="_undef_";bundleFeature="_undef_"]
+ expected: FAIL
+
+ [:passFeature="_undef_";bundleFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:passFeature="depth32float-stencil8";bundleFeature="_undef_"]
+ expected: FAIL
+
+ [:passFeature="depth32float-stencil8";bundleFeature="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,destination:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_format:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,destroyed,query_set:writeTimestamp:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,queue,submit:command_buffer,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_stencil_read_only_write_state:*]
+ [:encoderType="render%20pass";format="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="depth32float"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="depth16unorm"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="depth24plus"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="_undef_"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="depth32float"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="depth16unorm"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="depth24plus"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";format="depth32float-stencil8"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/23/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/23/cts.https.html.ini
new file mode 100644
index 0000000000..220b65117e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/23/cts.https.html.ini
@@ -0,0 +1,374 @@
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,empty:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,sample_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned:*]
+ [:formats=["r8unorm","r32float","rgba8unorm","rgba32float","r8unorm"\]]
+ expected: FAIL
+
+ [:formats=["r32float","rgba8unorm","rgba32float","r8unorm","r8unorm"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment:*]
+ [:format="depth32float"]
+ expected: FAIL
+
+ [:format="depth16unorm"]
+ expected: FAIL
+
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,usage:*]
+ [:usage=3]
+ expected: FAIL
+
+ [:usage=12]
+ expected: FAIL
+
+ [:usage=8]
+ expected: FAIL
+
+ [:usage=20]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,sample_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,aligned:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,different_size:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,array_layer_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,one_color_attachment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,sample_count:*]
+ [:encoderType="render%20pass";attachmentType="color"]
+ expected: FAIL
+
+ [:encoderType="render%20pass";attachmentType="depthstencil"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentType="color"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle";attachmentType="depthstencil"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,color_depth_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachments:*]
+ [:colorAttachmentsCount=8]
+ expected: FAIL
+
+ [:colorAttachmentsCount=9]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,non_multisampled:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,mipmap_level_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,error_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,one_depth_stencil_attachment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,layer_count:*]
+ [:arrayLayerCount=5;baseArrayLayer=0]
+ expected: FAIL
+
+ [:arrayLayerCount=1;baseArrayLayer=0]
+ expected: FAIL
+
+ [:arrayLayerCount=1;baseArrayLayer=9]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment,sample_counts_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment,depth_clear_value:*]
+ [:depthLoadOp="load";depthClearValue=-1]
+ expected: FAIL
+
+ [:depthLoadOp="load";depthClearValue=0]
+ expected: FAIL
+
+ [:depthLoadOp="load";depthClearValue=0.5]
+ expected: FAIL
+
+ [:depthLoadOp="load";depthClearValue=1]
+ expected: FAIL
+
+ [:depthLoadOp="load";depthClearValue=1.5]
+ expected: FAIL
+
+ [:depthLoadOp="clear";depthClearValue=-1]
+ expected: FAIL
+
+ [:depthLoadOp="clear";depthClearValue=0]
+ expected: FAIL
+
+ [:depthLoadOp="clear";depthClearValue=0.5]
+ expected: FAIL
+
+ [:depthLoadOp="clear";depthClearValue=1]
+ expected: FAIL
+
+ [:depthLoadOp="clear";depthClearValue=1.5]
+ expected: FAIL
+
+ [:depthLoadOp="_undef_";depthClearValue=-1]
+ expected: FAIL
+
+ [:depthLoadOp="_undef_";depthClearValue=0]
+ expected: FAIL
+
+ [:depthLoadOp="_undef_";depthClearValue=0.5]
+ expected: FAIL
+
+ [:depthLoadOp="_undef_";depthClearValue=1]
+ expected: FAIL
+
+ [:depthLoadOp="_undef_";depthClearValue=1.5]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,single_sample_count:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,format_supports_resolve:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,different_format:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,mip_level_count:*]
+ [:mipLevelCount=2;baseMipLevel=0]
+ expected: FAIL
+
+ [:mipLevelCount=1;baseMipLevel=0]
+ expected: FAIL
+
+ [:mipLevelCount=1;baseMipLevel=3]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,same_size:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/24/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/24/cts.https.html.ini
new file mode 100644
index 0000000000..3a3586a917
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/24/cts.https.html.ini
@@ -0,0 +1,5687 @@
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrites,query_set_type:*]
+ [:queryTypeA="occlusion";queryTypeB="occlusion"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryTypeA="occlusion";queryTypeB="timestamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryTypeA="timestamp";queryTypeB="occlusion"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryTypeA="timestamp";queryTypeB="timestamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:stencil_write:*]
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontDepthFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="frontPassOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backDepthFailOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="keep"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="zero"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="replace"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="invert"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="increment-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="decrement-clamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="increment-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";faceAndOpType="backPassOp";op="decrement-wrap"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:color_target_exists:*]
+ [:isAsync=false]
+ expected: FAIL
+
+ [:isAsync=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:format:*]
+ [:isAsync=false;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets,blend:*]
+ [:isAsync=false;format="r8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=false;format="r8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=false;format="r8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=false;format="r8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm";componentCount=4]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm";componentCount=1]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm";componentCount=2]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm";componentCount=3]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm";componentCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,resolve:resolve_attachment:*]
+ [:]
+ expected: FAIL
+
+ [:colorAttachmentSamples=1]
+ expected: FAIL
+
+ [:resolveTargetSamples=4]
+ expected: FAIL
+
+ [:resolveTargetUsage=1]
+ expected: FAIL
+
+ [:resolveTargetViewBaseMipLevel=1;resolveTargetHeight=4;resolveTargetWidth=4]
+ expected: FAIL
+
+ [:resolveTargetViewBaseMipLevel=1;resolveTargetViewMipCount=2;resolveTargetHeight=4;resolveTargetWidth=4]
+ expected: FAIL
+
+ [:resolveTargetInvalid=true]
+ expected: FAIL
+
+ [:resolveTargetViewMipCount=2]
+ expected: FAIL
+
+ [:resolveTargetViewBaseArrayLayer=1]
+ expected: FAIL
+
+ [:resolveTargetViewBaseArrayLayer=1;resolveTargetViewArrayLayerCount=2]
+ expected: FAIL
+
+ [:resolveTargetViewArrayLayerCount=2]
+ expected: FAIL
+
+ [:otherAttachmentFormat="bgra8unorm"]
+ expected: FAIL
+
+ [:colorAttachmentFormat="bgra8unorm"]
+ expected: FAIL
+
+ [:colorAttachmentFormat="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:resolveTargetFormat="bgra8unorm"]
+ expected: FAIL
+
+ [:resolveTargetFormat="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:colorAttachmentHeight=4]
+ expected: FAIL
+
+ [:colorAttachmentWidth=4]
+ expected: FAIL
+
+ [:resolveTargetHeight=4]
+ expected: FAIL
+
+ [:resolveTargetWidth=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:targets_format_filterable:*]
+ [:isAsync=false;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:stencil_test:*]
+ [:isAsync=false;format="depth32float";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="front";compare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";face="back";compare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="front";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";face="back";compare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="front";compare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";face="back";compare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:targets_format_renderable:*]
+ [:isAsync=false;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:location,superset:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:location,mismatch:*]
+ [:isAsync=false;outputs=["%40location(0)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=false;outputs=["%40location(0)%20__:%20f32"\];inputs=["%40location(1)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=false;outputs=["%40location(1)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=false;outputs=["%40location(0)%20__:%20f32","%40location(1)%20__:%20f32"\];inputs=["%40location(1)%20__:%20f32","%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=false;outputs=["%40location(1)%20__:%20f32","%40location(0)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32","%40location(1)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=true;outputs=["%40location(0)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=true;outputs=["%40location(0)%20__:%20f32"\];inputs=["%40location(1)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=true;outputs=["%40location(1)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=true;outputs=["%40location(0)%20__:%20f32","%40location(1)%20__:%20f32"\];inputs=["%40location(1)%20__:%20f32","%40location(0)%20__:%20f32"\]]
+ expected: FAIL
+
+ [:isAsync=true;outputs=["%40location(1)%20__:%20f32","%40location(0)%20__:%20f32"\];inputs=["%40location(0)%20__:%20f32","%40location(1)%20__:%20f32"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:occlusionQuerySet,query_set_type:*]
+ [:queryType="occlusion"]
+ expected: FAIL
+
+ [:queryType="timestamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestamp_writes_location:*]
+ [:locationA="beginning";locationB="beginning"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:locationA="beginning";locationB="end"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:locationA="end";locationB="beginning"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:locationA="end";locationB="end"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachmentBytesPerSample,aligned:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_write,frag_depth:*]
+ [:isAsync=false;format="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrite,same_query_index:*]
+ [:queryIndexA=0;queryIndexB=0]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndexA=0;queryIndexB=1]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndexA=1;queryIndexB=0]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndexA=1;queryIndexB=1]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachments:*]
+ [:isAsync=false;targetsLength=8]
+ expected: FAIL
+
+ [:isAsync=false;targetsLength=9]
+ expected: FAIL
+
+ [:isAsync=true;targetsLength=8]
+ expected: FAIL
+
+ [:isAsync=true;targetsLength=9]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_test:*]
+ [:isAsync=false;format="depth32float";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="never"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="less"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="less-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="greater"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="not-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="greater-equal"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthCompare="always"]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthCompare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="_undef_"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="never"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="less"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="less-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="greater"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="not-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="greater-equal"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthCompare="always"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_write:*]
+ [:isAsync=false;format="depth32float";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;format="depth16unorm";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;format="stencil8";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;format="depth24plus-stencil8";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;format="depth32float";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;format="depth16unorm";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;format="stencil8";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthWriteEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;format="depth24plus-stencil8";depthWriteEnabled=true]
+ expected: FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthWriteEnabled=false]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;format="depth32float-stencil8";depthWriteEnabled=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthWriteEnabled=false]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;format="depth32float-stencil8";depthWriteEnabled=true]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:targets_blend:*]
+ [:isAsync=false;component="color"]
+ expected: FAIL
+
+ [:isAsync=false;component="alpha"]
+ expected: FAIL
+
+ [:isAsync=true;component="color"]
+ expected: FAIL
+
+ [:isAsync=true;component="alpha"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrite,query_index:*]
+ [:queryIndex=0]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndex=1]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndex=2]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:queryIndex=3]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets:*]
+ [:isAsync=false;format="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=false;format="rgba32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="r32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba8sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rg32float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba16float"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32uint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32sint"]
+ expected: FAIL
+
+ [:isAsync=true;format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachmentBytesPerSample,unaligned:*]
+ [:formats=["r8unorm","r32float","rgba8unorm","rgba32float","r8unorm"\]]
+ expected: FAIL
+
+ [:formats=["r32float","rgba8unorm","rgba32float","r8unorm","r8unorm"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,fragment_state:targets_write_mask:*]
+ [:isAsync=false;writeMask=0]
+ expected: FAIL
+
+ [:isAsync=false;writeMask=15]
+ expected: FAIL
+
+ [:isAsync=false;writeMask=16]
+ expected: FAIL
+
+ [:isAsync=false;writeMask=2147483649]
+ expected: FAIL
+
+ [:isAsync=true;writeMask=0]
+ expected: FAIL
+
+ [:isAsync=true;writeMask=15]
+ expected: FAIL
+
+ [:isAsync=true;writeMask=16]
+ expected: FAIL
+
+ [:isAsync=true;writeMask=2147483649]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:*]
+ [:readonly=true]
+ expected: FAIL
+
+ [:readonly=true;depthStoreOp="discard"]
+ expected: FAIL
+
+ [:readonly=true;stencilStoreOp="discard"]
+ expected: FAIL
+
+ [:readonly=false]
+ expected: FAIL
+
+ [:readonly=false;depthReadOnly=true]
+ expected: FAIL
+
+ [:readonly=false;stencilReadOnly=true]
+ expected: FAIL
+
+ [:readonly="_undef_"]
+ expected: FAIL
+
+ [:readonly="_undef_";depthReadOnly=true]
+ expected: FAIL
+
+ [:readonly="_undef_";stencilReadOnly=true]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/25/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/25/cts.https.html.ini
new file mode 100644
index 0000000000..59eca89024
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/25/cts.https.html.ini
@@ -0,0 +1,991 @@
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,vertex:*]
+ [:isAsync=true;vertexConstants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cb":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cb":-2147483649}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:type:*]
+ [:isAsync=false;output="f32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=false;output="f32";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=false;output="i32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=false;output="i32";input="u32"]
+ expected: FAIL
+
+ [:isAsync=false;output="u32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=false;output="u32";input="i32"]
+ expected: FAIL
+
+ [:isAsync=false;output="vec2%3Cf32%3E";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=false;output="vec2%3Cf32%3E";input="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=false;output="vec2%3Cf32%3E";input="f32"]
+ expected: FAIL
+
+ [:isAsync=false;output="vec3%3Cf32%3E";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=true;output="f32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=true;output="f32";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=true;output="i32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=true;output="i32";input="u32"]
+ expected: FAIL
+
+ [:isAsync=true;output="u32";input="f32"]
+ expected: FAIL
+
+ [:isAsync=true;output="u32";input="i32"]
+ expected: FAIL
+
+ [:isAsync=true;output="vec2%3Cf32%3E";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=true;output="vec2%3Cf32%3E";input="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:isAsync=true;output="vec2%3Cf32%3E";input="f32"]
+ expected: FAIL
+
+ [:isAsync=true;output="vec3%3Cf32%3E";input="vec2%3Cf32%3E"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,type_error,vertex:*]
+ [:isAsync=true;vertexConstants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,primitive_state:unclipped_depth:*]
+ [:isAsync=false;unclippedDepth=false]
+ expected: FAIL
+
+ [:isAsync=false;unclippedDepth=true]
+ expected: FAIL
+
+ [:isAsync=true;unclippedDepth=false]
+ expected: FAIL
+
+ [:isAsync=true;unclippedDepth=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,misc:basic:*]
+ [:isAsync=false]
+ expected: FAIL
+
+ [:isAsync=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,multisample_state:alpha_to_coverage,count:*]
+ [:isAsync=false;alphaToCoverageEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;alphaToCoverageEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;alphaToCoverageEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;alphaToCoverageEnabled=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:location,subset:*]
+ [:isAsync=false]
+ expected: FAIL
+
+ [:isAsync=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:max_shader_variable_location:*]
+ [:isAsync=false;locationDelta=0]
+ expected: FAIL
+
+ [:isAsync=false;locationDelta=-1]
+ expected: FAIL
+
+ [:isAsync=false;locationDelta=-2]
+ expected: FAIL
+
+ [:isAsync=true;locationDelta=0]
+ expected: FAIL
+
+ [:isAsync=true;locationDelta=-1]
+ expected: FAIL
+
+ [:isAsync=true;locationDelta=-2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:identifier,fragment:*]
+ [:isAsync=true;fragmentConstants={}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"1":1,"1000":1,"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"xxx":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"1":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"2":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"b":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"a":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"1":1,"b":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"1":1,"1000":1,"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"xxx":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"1":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"2":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"b":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"a":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"1":1,"b":1}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,misc:vertex_state_only:*]
+ [:isAsync=false]
+ expected: FAIL
+
+ [:isAsync=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:max_components_count,input:*]
+ [:isAsync=false;numScalarDelta=0;useExtraBuiltinInputs=false]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=0;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=1;useExtraBuiltinInputs=false]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=-3;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=-2;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=0;useExtraBuiltinInputs=false]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=0;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=1;useExtraBuiltinInputs=false]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=-3;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=-2;useExtraBuiltinInputs=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:max_components_count,output:*]
+ [:isAsync=false;numScalarDelta=0;topology="triangle-list"]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=0;topology="point-list"]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=1;topology="triangle-list"]
+ expected: FAIL
+
+ [:isAsync=false;numScalarDelta=-1;topology="point-list"]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=0;topology="triangle-list"]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=0;topology="point-list"]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=1;topology="triangle-list"]
+ expected: FAIL
+
+ [:isAsync=true;numScalarDelta=-1;topology="point-list"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:identifier,vertex:*]
+ [:isAsync=true;vertexConstants={}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"1":1,"1000":1,"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"xxx":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"1":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"2":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"z":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"w":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"1":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"1":1,"1000":1,"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"xxx":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"1":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"2":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"w":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"1":1,"z":1}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,multisample_state:alpha_to_coverage,sample_mask:*]
+ [:isAsync=false;alphaToCoverageEnabled=false]
+ expected: FAIL
+
+ [:isAsync=false;alphaToCoverageEnabled=true]
+ expected: FAIL
+
+ [:isAsync=true;alphaToCoverageEnabled=false]
+ expected: FAIL
+
+ [:isAsync=true;alphaToCoverageEnabled=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,misc:pipeline_layout,device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,f16,fragment:*]
+ [:isAsync=true;fragmentConstants={"cf16":-65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":-98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":-3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":-3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;fragmentConstants={"cf16":3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":-65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":-98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":-3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":-3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;fragmentConstants={"cf16":3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:uninitialized,fragment:*]
+ [:isAsync=true;fragmentConstants={}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"r":1,"b":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"r":1,"g":1,"b":1,"a":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"r":1,"g":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"r":1,"b":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"r":1,"g":1,"b":1,"a":1}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,multisample_state:count:*]
+ [:isAsync=false]
+ expected: FAIL
+
+ [:isAsync=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,primitive_state:strip_index_format:*]
+ [:isAsync=false;topology="_undef_";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="_undef_";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="_undef_";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=false;topology="point-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="point-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="point-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-strip";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-strip";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="line-strip";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-strip";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-strip";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=false;topology="triangle-strip";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="_undef_";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="_undef_";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="_undef_";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="point-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="point-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="point-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-strip";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-strip";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="line-strip";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-list";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-list";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-list";stripIndexFormat="uint32"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-strip";stripIndexFormat="_undef_"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-strip";stripIndexFormat="uint16"]
+ expected: FAIL
+
+ [:isAsync=true;topology="triangle-strip";stripIndexFormat="uint32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:interpolation_type:*]
+ [:isAsync=false;output="";input=""]
+ expected: FAIL
+
+ [:isAsync=false;output="";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=false;output="";input="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:isAsync=false;output="";input="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective)";input=""]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(linear)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(linear)";input="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(flat)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(linear,%20center)";input="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:isAsync=true;output="";input=""]
+ expected: FAIL
+
+ [:isAsync=true;output="";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="";input="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:isAsync=true;output="";input="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective)";input=""]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(linear)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(linear)";input="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(flat)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(linear,%20center)";input="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,inter_stage:interpolation_sampling:*]
+ [:isAsync=false;output="%40interpolate(perspective)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective)";input="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective)";input="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(linear,%20center)";input="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(flat)";input="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective,%20center)";input="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective,%20center)";input="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:isAsync=false;output="%40interpolate(perspective,%20centroid)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective)";input="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective)";input="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(linear,%20center)";input="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(flat)";input="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective,%20center)";input="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective,%20center)";input="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:isAsync=true;output="%40interpolate(perspective,%20centroid)";input="%40interpolate(perspective)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,type_error,fragment:*]
+ [:isAsync=true;fragmentConstants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":"_nan_"}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":"_posinfinity_"}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":"_neginfinity_"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,fragment:*]
+ [:isAsync=true;fragmentConstants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=true;fragmentConstants={"cb":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cu":0}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cu":-1}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cu":4294967295}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cu":4294967296}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"ci":-2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"ci":-2147483649}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"ci":2147483647}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"ci":2147483648}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":-3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":-3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":3.4028234663852886e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cf":3.4028235677973366e%2B38}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cb":1.7976931348623157e%2B308}]
+ expected: FAIL
+
+ [:isAsync=false;fragmentConstants={"cb":-2147483649}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,f16,vertex:*]
+ [:isAsync=true;vertexConstants={"cf16":-65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":-98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":-3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":-3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=true;vertexConstants={"cf16":3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":-65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":-98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":65504}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":98288}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":-3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":3.4028234663852886e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":-3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:isAsync=false;vertexConstants={"cf16":3.4028235677973366e%2B38}]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,overrides:uninitialized,vertex:*]
+ [:isAsync=true;vertexConstants={}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"x":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=true;vertexConstants={"x":1,"y":1,"z":1,"w":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"x":1,"y":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"x":1,"z":1}]
+ expected: FAIL
+
+ [:isAsync=false;vertexConstants={"x":1,"y":1,"z":1,"w":1}]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/26/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/26/cts.https.html.ini
new file mode 100644
index 0000000000..d67d4bcf30
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/26/cts.https.html.ini
@@ -0,0 +1,2325 @@
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_shaderLocation_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_contained_in_stride:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_no_draw:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="index"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="index"]
+ expected: FAIL
+
+ [:usage0="index";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="index";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="index";usage1="index"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_type_matches_attribute_format:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,shader_module:invalid,vertex:*]
+ [:isAsync=true;isVertexShaderValid=true]
+ expected: FAIL
+
+ [:isAsync=true;isVertexShaderValid=false]
+ expected: FAIL
+
+ [:isAsync=false;isVertexShaderValid=true]
+ expected: FAIL
+
+ [:isAsync=false;isVertexShaderValid=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_dispatch:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_color:*]
+ [:compute=false;type0="sampled-texture";type1="sampled-texture"]
+ expected: FAIL
+
+ [:compute=false;type0="sampled-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+ [:compute=false;type0="sampled-texture";type1="render-target"]
+ expected: FAIL
+
+ [:compute=false;type0="writeonly-storage-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+ [:compute=false;type0="writeonly-storage-texture";type1="render-target"]
+ expected: FAIL
+
+ [:compute=false;type0="render-target";type1="render-target"]
+ expected: FAIL
+
+ [:compute=true;type0="sampled-texture";type1="sampled-texture"]
+ expected: FAIL
+
+ [:compute=true;type0="sampled-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+ [:compute=true;type0="writeonly-storage-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_draw:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="index"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="index"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="index";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="index";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="index";usage1="index"]
+ expected: FAIL
+
+ [:usage0="index";usage1="indexedIndirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,shader_module:invalid,fragment:*]
+ [:isAsync=true;isFragmentShaderValid=true]
+ expected: FAIL
+
+ [:isAsync=true;isFragmentShaderValid=false]
+ expected: FAIL
+
+ [:isAsync=false;isFragmentShaderValid=true]
+ expected: FAIL
+
+ [:isAsync=false;isFragmentShaderValid=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_one_dispatch:*]
+ [:usage0AccessibleInDispatch=true;usage1AccessibleInDispatch=true;dispatchBeforeUsage1=false]
+ expected: FAIL
+
+ [:usage0AccessibleInDispatch=true;usage1AccessibleInDispatch=false;dispatchBeforeUsage1=true]
+ expected: FAIL
+
+ [:usage0AccessibleInDispatch=true;usage1AccessibleInDispatch=false;dispatchBeforeUsage1=false]
+ expected: FAIL
+
+ [:usage0AccessibleInDispatch=false;usage1AccessibleInDispatch=true;dispatchBeforeUsage1=false]
+ expected: FAIL
+
+ [:usage0AccessibleInDispatch=false;usage1AccessibleInDispatch=false;dispatchBeforeUsage1=true]
+ expected: FAIL
+
+ [:usage0AccessibleInDispatch=false;usage1AccessibleInDispatch=false;dispatchBeforeUsage1=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_no_dispatch:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_buffer_array_stride_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_attribute_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_input_location_in_vertex_state:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_buffer_array_stride_limit_alignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:many_attributes_overlapping:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_input_location_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_one_draw:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="index"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="index"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="index";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="index";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="index";usage1="index"]
+ expected: FAIL
+
+ [:usage0="index";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="index";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="index"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="index"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_compute_pass_with_two_dispatches:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="indirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,shader_module:device_mismatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,buffer_usages_in_copy_and_pass:*]
+ [:usage0="copy-src";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="uniform";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="uniform";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="storage";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="storage";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="read-only-storage";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="read-only-storage";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="vertex";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="index";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="indirect";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="indirect";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="indexedIndirect";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="uniform";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="uniform";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="storage";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="storage";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="read-only-storage";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="read-only-storage";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="vertex";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="index";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="indirect";pass="render"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="indirect";pass="compute"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="indexedIndirect";pass="render"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="copy-src";pass="compute"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="copy-dst";pass="compute"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-src";pass="compute"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-dst";pass="compute"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="copy-src";pass="compute"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="copy-dst";pass="compute"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="index";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="index";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="copy-src";pass="compute"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="copy-dst";pass="compute"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="copy-src";pass="render"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="copy-dst";pass="render"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_offset_alignment:*]
+ [:format="uint8x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=1]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=254]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=253]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=1]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=2046]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=2045]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="uint8x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="uint8x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=1]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=254]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=253]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=1]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=2046]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=2045]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="sint8x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="sint8x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=1]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=254]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=253]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=1]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=2046]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=2045]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="unorm8x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="unorm8x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=1]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=254]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=253]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=1]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=2046]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=2045]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="snorm8x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="snorm8x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="uint16x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="uint16x4";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="sint16x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="sint16x4";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="unorm16x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="unorm16x4";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="snorm16x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="snorm16x4";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="float16x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="float16x4";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="float32";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="float32";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="float32x2";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=6]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=12]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=256;offset=242]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=6]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=12]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="float32x3";arrayStride=2048;offset=2034]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=16]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=232]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=236]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=16]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=2024]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=2028]
+ expected: FAIL
+
+ [:format="float32x4";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="uint32";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="uint32x2";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=6]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=12]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=256;offset=242]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=6]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=12]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="uint32x3";arrayStride=2048;offset=2034]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=16]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=232]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=236]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=16]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=2024]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=2028]
+ expected: FAIL
+
+ [:format="uint32x4";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=252]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=250]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=2044]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=2042]
+ expected: FAIL
+
+ [:format="sint32";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=248]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=256;offset=246]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=2040]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="sint32x2";arrayStride=2048;offset=2038]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=6]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=12]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=244]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=256;offset=242]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=6]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=12]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=2036]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="sint32x3";arrayStride=2048;offset=2034]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=0]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=8]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=16]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=2]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=4]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=240]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=232]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=236]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=256;offset=238]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=0]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=8]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=16]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=2]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=4]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=2032]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=2024]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=2028]
+ expected: FAIL
+
+ [:format="sint32x4";arrayStride=2048;offset=2030]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_buffer_limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_shaderLocation_unique:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_two_draws:*]
+ [:usage0="uniform";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="index"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="uniform";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="index"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="read-only-storage";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="index"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="vertex";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="index";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="index";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="index";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="index";usage1="index"]
+ expected: FAIL
+
+ [:usage0="index";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="index";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="index"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="indirect";usage1="indexedIndirect"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="uniform"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="read-only-storage"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="vertex"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="index"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="indirect"]
+ expected: FAIL
+
+ [:usage0="indexedIndirect";usage1="indexedIndirect"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/27/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/27/cts.https.html.ini
new file mode 100644
index 0000000000..c3bcda9197
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/27/cts.https.html.ini
@@ -0,0 +1,5645 @@
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,dispatch:*]
+ [:dispatch="none"]
+ expected: FAIL
+
+ [:dispatch="direct"]
+ expected: FAIL
+
+ [:dispatch="indirect"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,shader_module,entry_point:compute:*]
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_texture_in_bind_groups:*]
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":0,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":1};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":0,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":1};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":0,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":1};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":0,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":1};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="depth-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:view0Levels={"base":1,"count":2};view0Layers={"base":1,"count":2};view1Levels={"base":1,"count":2};view1Layers={"base":1,"count":2};aspect0="stencil-only";aspect1="stencil-only";inSamePass=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,pass_boundary,render:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachments:*]
+ [:layer0=0;level0=0;layer1=0;level1=0;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=0;level0=0;layer1=0;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=0;layer1=0;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=0;layer1=1;level1=0;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=0;level0=0;layer1=1;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=0;layer1=1;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=0;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=0;level1=1;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=0;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=1;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=1;level1=1;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=0;level0=1;layer1=1;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=0;level1=0;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=0;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=0;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=1;level1=0;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=1;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=0;layer1=1;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=0;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=0;level1=1;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=0;level1=1;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=1;level1=0;inSamePass=false]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=1;level1=1;inSamePass=true]
+ expected: FAIL
+
+ [:layer0=1;level0=1;layer1=1;level1=1;inSamePass=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,shader_module,entry_point:vertex:*]
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachment_and_bind_group:*]
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=0;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;bgUsage="storage";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=true]
+ expected: FAIL
+
+ [:colorAttachmentLevel=1;colorAttachmentLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;bgUsage="texture";inSamePass=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:shader_stages_and_visibility,attachment_write:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_attachment_and_bind_group:*]
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=0;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=0;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=0;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=1;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=0;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=1;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=true;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="depth-only";inSamePass=false]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=true]
+ expected: FAIL
+
+ [:dsLevel=1;dsLayer=1;bgLevel=1;bgLevelCount=2;bgLayer=1;bgLayerCount=2;dsReadOnly=false;bgAspect="stencil-only";inSamePass=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,multiple_bind_groups:*]
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":0,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":1};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="storage";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":0,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":1};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":0,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":1};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="storage";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":0,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":1};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=true]
+ expected: FAIL
+
+ [:bg0Levels={"base":1,"count":2};bg0Layers={"base":1,"count":2};bg1Levels={"base":1,"count":2};bg1Layers={"base":1,"count":2};bgUsage0="texture";bgUsage1="texture";inSamePass=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,shader_module,overrides:name_conflict:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_color_texture:*]
+ [:useDifferentTextureAsTexture2=true;baseLayer2=0;view2Binding="texture";hasConflict=true]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=true;baseLayer2=0;view2Binding="texture";hasConflict=false]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=0;view2Binding="texture";hasConflict=true]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=0;view2Binding="texture";hasConflict=false]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=0;view2Binding="storage";hasConflict=true]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=0;view2Binding="storage";hasConflict=false]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=1;view2Binding="texture";hasConflict=true]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=1;view2Binding="texture";hasConflict=false]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=1;view2Binding="storage";hasConflict=true]
+ expected: FAIL
+
+ [:useDifferentTextureAsTexture2=false;baseLayer2=1;view2Binding="storage";hasConflict=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,shader_module,overrides:id_conflict:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,shader_module,entry_point:fragment:*]
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=true;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint=""]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cu0000a"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%20"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="ma%20in"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main";stageEntryPoint="main%5Cn"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="mian"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mian";stageEntryPoint="main"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="mainmain"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="mainmain";stageEntryPoint="foo"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="main_t12V5"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="main_t12V3";stageEntryPoint="_main_t12V3"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="s%C3%A9quen%C3%A7age"]
+ expected: FAIL
+
+ [:isAsync=false;shaderModuleEntryPoint="s%C3%A9quen%C3%A7age";stageEntryPoint="sequencage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:*]
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="depth32float"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="depth24plus"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="depth32float"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="depth16unorm"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="depth24plus"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="depth32float"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="depth24plus"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="depth32float"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="depth16unorm"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="depth24plus"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="depth32float"]
+ expected: FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="depth16unorm"]
+ expected: FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="stencil8"]
+ expected: FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="depth24plus"]
+ expected: FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=false;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:compute=false;binding0InBundle=false;binding1InBundle=true;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=false;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:compute=false;binding0InBundle=true;binding1InBundle=true;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:compute=true;binding0InBundle=false;binding1InBundle=false;format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:bindings_in_bundle:*]
+ [:type0="render-target";type1="sampled-texture"]
+ expected: FAIL
+
+ [:type0="render-target";type1="multisampled-texture"]
+ expected: FAIL
+
+ [:type0="render-target";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+ [:type0="sampled-texture";type1="render-target"]
+ expected: FAIL
+
+ [:type0="sampled-texture";type1="sampled-texture"]
+ expected: FAIL
+
+ [:type0="sampled-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+ [:type0="multisampled-texture";type1="render-target"]
+ expected: FAIL
+
+ [:type0="multisampled-texture";type1="multisampled-texture"]
+ expected: FAIL
+
+ [:type0="writeonly-storage-texture";type1="render-target"]
+ expected: FAIL
+
+ [:type0="writeonly-storage-texture";type1="sampled-texture"]
+ expected: FAIL
+
+ [:type0="writeonly-storage-texture";type1="writeonly-storage-texture"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,pass_boundary,compute:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,basic,render:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:shader_stages_and_visibility,storage_write:*]
+ [:compute=false]
+ expected: FAIL
+
+ [:compute=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createBuffer:*]
+ [:usageType="MAP_READ"]
+ expected: FAIL
+
+ [:usageType="MAP_WRITE"]
+ expected: FAIL
+
+ [:usageType="INDEX"]
+ expected: FAIL
+
+ [:usageType="VERTEX"]
+ expected: FAIL
+
+ [:usageType="UNIFORM"]
+ expected: FAIL
+
+ [:usageType="STORAGE"]
+ expected: FAIL
+
+ [:usageType="INDIRECT"]
+ expected: FAIL
+
+ [:usageType="QUERY_RESOLVE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:unused_bindings_in_pipeline:*]
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=false;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=false;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=false;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="common";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="before";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="middle";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="after";callDrawOrDispatch=true]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=false]
+ expected: FAIL
+
+ [:compute=true;useBindGroup0=true;useBindGroup1=true;setBindGroupsOrder="reversed";setPipeline="none";callDrawOrDispatch=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:replaced_binding:*]
+ [:compute=false;callDrawOrDispatch=false;entry={"texture":{}}]
+ expected: FAIL
+
+ [:compute=false;callDrawOrDispatch=false;entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+ [:compute=false;callDrawOrDispatch=true;entry={"texture":{}}]
+ expected: FAIL
+
+ [:compute=false;callDrawOrDispatch=true;entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+ [:compute=true;callDrawOrDispatch=false;entry={"texture":{}}]
+ expected: FAIL
+
+ [:compute=true;callDrawOrDispatch=false;entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+ [:compute=true;callDrawOrDispatch=true;entry={"texture":{}}]
+ expected: FAIL
+
+ [:compute=true;callDrawOrDispatch=true;entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,texture_usages_in_copy_and_render_pass:*]
+ [:usage0="copy-src";usage1="copy-src"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="copy-dst"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="texture"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="copy-src";usage1="color-attachment"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="copy-src"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="copy-dst"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="texture"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="storage"]
+ expected: FAIL
+
+ [:usage0="copy-dst";usage1="color-attachment"]
+ expected: FAIL
+
+ [:usage0="texture";usage1="copy-src"]
+ expected: FAIL
+
+ [:usage0="texture";usage1="copy-dst"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-src"]
+ expected: FAIL
+
+ [:usage0="storage";usage1="copy-dst"]
+ expected: FAIL
+
+ [:usage0="color-attachment";usage1="copy-src"]
+ expected: FAIL
+
+ [:usage0="color-attachment";usage1="copy-dst"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_unused_bind_group:*]
+ [:inRenderPass=true;hasConflict=true]
+ expected: FAIL
+
+ [:inRenderPass=true;hasConflict=false]
+ expected: FAIL
+
+ [:inRenderPass=false;hasConflict=true]
+ expected: FAIL
+
+ [:inRenderPass=false;hasConflict=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_depth_stencil_texture:*]
+ [:bindAspect="depth-only";depthStencilReadOnly=true]
+ expected: FAIL
+
+ [:bindAspect="depth-only";depthStencilReadOnly=false]
+ expected: FAIL
+
+ [:bindAspect="stencil-only";depthStencilReadOnly=true]
+ expected: FAIL
+
+ [:bindAspect="stencil-only";depthStencilReadOnly=false]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/28/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/28/cts.https.html.ini
new file mode 100644
index 0000000000..db8b345a96
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/28/cts.https.html.ini
@@ -0,0 +1,824 @@
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,draw:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createQuerySet:*]
+ [:type="occlusion"]
+ expected: FAIL
+
+ [:type="timestamp"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createSampler:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:queue,writeBuffer:*]
+ [:numElements=4]
+ expected: FAIL
+
+ [:numElements=8]
+ expected: FAIL
+
+ [:numElements=16]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,uncompressed_format:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,uncompressed_format:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createRenderBundleEncoder:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createComputePipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,compressed_format:*]
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="eac-r11unorm"]
+ expected: FAIL
+
+ [:format="eac-r11snorm"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,computePass,dispatch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createBindGroupLayout:*]
+ [:entry={"buffer":{"type":"uniform"}}]
+ expected: FAIL
+
+ [:entry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:entry={"buffer":{"type":"read-only-storage"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"comparison"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"non-filtering"}}]
+ expected: FAIL
+
+ [:entry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:entry={"texture":{"multisampled":true}}]
+ expected: FAIL
+
+ [:entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createBindGroup:*]
+ [:resourceType="uniformBuf";entry={"buffer":{"type":"uniform"}}]
+ expected: FAIL
+
+ [:resourceType="storageBuf";entry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:resourceType="storageBuf";entry={"buffer":{"type":"read-only-storage"}}]
+ expected: FAIL
+
+ [:resourceType="filtSamp";entry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:resourceType="nonFiltSamp";entry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:resourceType="nonFiltSamp";entry={"sampler":{"type":"non-filtering"}}]
+ expected: FAIL
+
+ [:resourceType="compareSamp";entry={"sampler":{"type":"comparison"}}]
+ expected: FAIL
+
+ [:resourceType="sampledTex";entry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:resourceType="sampledTexMS";entry={"texture":{"multisampled":true}}]
+ expected: FAIL
+
+ [:resourceType="storageTex";entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,clearBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createShaderModule:*]
+ [:stage="VERTEX"]
+ expected: FAIL
+
+ [:stage="FRAGMENT"]
+ expected: FAIL
+
+ [:stage="COMPUTE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,resolveQuerySet:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,compressed_format:*]
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected: FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="eac-r11unorm"]
+ expected: FAIL
+
+ [:format="eac-r11snorm"]
+ expected: FAIL
+
+ [:format="eac-rg11unorm"]
+ expected: FAIL
+
+ [:format="eac-rg11snorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected: FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToTexture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createRenderPipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createCommandEncoder:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:createPipelineLayout:*]
+ [:entry={"buffer":{"type":"uniform"}}]
+ expected: FAIL
+
+ [:entry={"buffer":{"type":"storage"}}]
+ expected: FAIL
+
+ [:entry={"buffer":{"type":"read-only-storage"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"comparison"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"filtering"}}]
+ expected: FAIL
+
+ [:entry={"sampler":{"type":"non-filtering"}}]
+ expected: FAIL
+
+ [:entry={"texture":{"multisampled":false}}]
+ expected: FAIL
+
+ [:entry={"texture":{"multisampled":true}}]
+ expected: FAIL
+
+ [:entry={"storageTexture":{"access":"write-only","format":"rgba8unorm"}}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,writeTimestamp:*]
+ [:type="occlusion"]
+ expected: FAIL
+
+ [:type="timestamp"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,renderBundle:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToTexture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToBuffer:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/29/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/29/cts.https.html.ini
new file mode 100644
index 0000000000..069449d23b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/29/cts.https.html.ini
@@ -0,0 +1,592 @@
+[cts.https.html?q=webgpu:examples:basic,plain_cases:*]
+ [:x=2;y=2]
+ expected: FAIL
+
+ [:x=-10;y=-10]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:gpu,with_texture_compression,bc:*]
+ [:textureCompressionBC=false]
+ expected: FAIL
+
+ [:textureCompressionBC=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,async:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:begin_render_bundle_encoder:*]
+ [:]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:examples:test_name:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:gpu,async:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:create_texture:*]
+ [:sampleCount=1]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:sampleCount=4]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,destroy:base:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:not_implemented_yet,with_plan:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,builder_subcases:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,plain_cases_private:*]
+ [:x=2;y=4]
+ expected: FAIL
+
+ [:x=-10;y=18]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:gpu,buffers:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,canvas:*]
+ [:canvasType="onscreen";contextType="2d"]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextType="webgl"]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextType="webgl2"]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextType="webgpu"]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextType="2d"]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextType="webgl"]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextType="webgl2"]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextType="webgpu"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:not_implemented_yet,without_plan:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,builder_cases_subcases:*]
+ [:x=1]
+ expected: FAIL
+
+ [:x=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,uncompressed_format:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,builder_subcases_short:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,destroy:submit_a_destroyed_texture_as_attachment:*]
+ [:depthStencilTextureAspect="all";colorTextureState="valid";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="valid";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="valid";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedAfterEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="all";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="valid";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="valid";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="valid";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="depth-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="valid";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="valid";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="valid";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedBeforeEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="valid"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedBeforeEncode"]
+ expected: FAIL
+
+ [:depthStencilTextureAspect="stencil-only";colorTextureState="destroyedAfterEncode";depthStencilTextureState="destroyedAfterEncode"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,imageBitmap:*]
+ [:]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,compressed_format:*]
+ [:format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,destroy:twice:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:basic,builder_cases:*]
+ [:x=1;y=1]
+ expected: FAIL
+
+ [:x=1;y=2]
+ expected: FAIL
+
+ [:x=2;y=1]
+ expected: FAIL
+
+ [:x=2;y=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:create_render_pipeline:*]
+ [:]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:begin_render_pass:*]
+ [:]
+ expected:
+ if os == "mac": PASS
+ FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/3/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/3/cts.https.html.ini
new file mode 100644
index 0000000000..fc49bf594f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/3/cts.https.html.ini
@@ -0,0 +1,1044 @@
+[cts.https.html?q=webgpu:api,operation,device,lost:lost_on_destroy:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute,basic:memcpy:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,device,lost:same_object:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,render,state_tracking:change_pipeline_before_and_after_vertex_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute,basic:large_dispatch:*]
+ [:dispatchSize=256]
+ expected: FAIL
+
+ [:dispatchSize=2048]
+ expected: FAIL
+
+ [:dispatchSize=315]
+ expected: FAIL
+
+ [:dispatchSize=628]
+ expected: FAIL
+
+ [:dispatchSize=2179]
+ expected: FAIL
+
+ [:dispatchSize=65535]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:shared_shader_module:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_but_not_used_in_draw:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:multi_entry_points:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:precision:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,device,lost:not_lost_on_gc:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_before_pipeline:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_multiple_sets:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:basic:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_draws_in_one_render_pass:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:one_bind_group_multiple_slots:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,programmable,state_tracking:compatible_pipelines:*]
+ [:encoderType="compute%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20pass"]
+ expected: FAIL
+
+ [:encoderType="render%20bundle"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:wr:*]
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,labels:object_has_descriptor_label:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:rw:*]
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_without_changing_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:numeric_id:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_without_changing_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,compute_pipeline,overrides:workgroup_size:*]
+ [:isAsync=true;type="u32";size=3;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=3;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=3;v="z"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=16;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=16;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=16;v="z"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=64;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=64;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="u32";size=64;v="z"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=3;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=3;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=3;v="z"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=16;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=16;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=16;v="z"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=64;v="x"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=64;v="y"]
+ expected: FAIL
+
+ [:isAsync=true;type="i32";size=64;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=3;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=3;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=3;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=16;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=16;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=16;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=64;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=64;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="u32";size=64;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=3;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=3;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=3;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=16;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=16;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=16;v="z"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=64;v="x"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=64;v="y"]
+ expected: FAIL
+
+ [:isAsync=false;type="i32";size=64;v="z"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:ww:*]
+ [:boundary="queue-op";writeOps=["write-buffer","write-buffer"\];contexts=["queue","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","b2b-copy"\];contexts=["queue","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","t2b-copy"\];contexts=["queue","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","write-buffer"\];contexts=["command-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","write-buffer"\];contexts=["command-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["compute-pass-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["render-pass-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["render-bundle-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="pass";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="dispatch";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_before_non_indexed_draw:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/30/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/30/cts.https.html.ini
new file mode 100644
index 0000000000..f98f35db93
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/30/cts.https.html.ini
@@ -0,0 +1,651 @@
+[cts.https.html?q=webgpu:idl,constants,flags:ColorWrite,values:*]
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:or:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_or:*]
+ [:type="i32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:idl,constants,flags:ShaderStage,values:*]
+
+[cts.https.html?q=webgpu:idl,constants,flags:TextureUsage,values:*]
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:and:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:binary_mixed:*]
+ [:name="ArithAndLogical"]
+ expected: FAIL
+
+ [:name="LogicalAndArith"]
+ expected: FAIL
+
+ [:name="ArithAndLogical_ShortCircuit"]
+ expected: FAIL
+
+ [:name="LogicalAndArith_ShortCircuit"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:examples:gpu,with_texture_compression,etc2:*]
+ [:textureCompressionETC2=false]
+ expected: FAIL
+
+ [:textureCompressionETC2=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:index_accessor:*]
+ [:name="LeftSE"]
+ expected: FAIL
+
+ [:name="RightSE"]
+ expected: FAIL
+
+ [:name="BothSE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:call:*]
+ [:name="OneSE"]
+ expected: FAIL
+
+ [:name="AllSE"]
+ expected: FAIL
+
+ [:name="MiddleNotSE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_and:*]
+ [:type="i32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_exclusive_or:*]
+ [:type="i32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="i32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:type="u32";inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:binary_arith:*]
+ [:name="BothSE"]
+ expected: FAIL
+
+ [:name="LeftSE"]
+ expected: FAIL
+
+ [:name="RightSE"]
+ expected: FAIL
+
+ [:name="ThreeSE"]
+ expected: FAIL
+
+ [:name="LeftmostSE"]
+ expected: FAIL
+
+ [:name="RightmostSE"]
+ expected: FAIL
+
+ [:name="MiddleSE"]
+ expected: FAIL
+
+ [:name="LiteralAndSEAndVar"]
+ expected: FAIL
+
+ [:name="VarAndSEAndLiteral"]
+ expected: FAIL
+
+ [:name="SEAndVarAndLiteral"]
+ expected: FAIL
+
+ [:name="VarAndLiteralAndSE"]
+ expected: FAIL
+
+ [:name="MemberAccessAndSE"]
+ expected: FAIL
+
+ [:name="SEAndMemberAccess"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:idl,constants,flags:BufferUsage,count:*]
+
+[cts.https.html?q=webgpu:idl,constants,flags:TextureUsage,count:*]
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:assignment:*]
+ [:name="ToArray1D"]
+ expected: FAIL
+
+ [:name="ToArray2D"]
+ expected: FAIL
+
+ [:name="ToArrayFromArray"]
+ expected: FAIL
+
+ [:name="ToArrayIndexedByArrayIndexedBySE"]
+ expected: FAIL
+
+ [:name="ToVec_BothSE"]
+ expected: FAIL
+
+ [:name="ToVec_LeftSE"]
+ expected: FAIL
+
+ [:name="ToVec_RightSE"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:and_short_circuit:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:idl,constants,flags:ShaderStage,count:*]
+
+[cts.https.html?q=webgpu:idl,constants,flags:ColorWrite,count:*]
+
+[cts.https.html?q=webgpu:idl,constants,flags:BufferUsage,values:*]
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:member_accessor:*]
+ [:name="Vec"]
+ expected: FAIL
+
+ [:name="Struct"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:or_short_circuit:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:binary_logical:*]
+ [:name="BothSE"]
+ expected: FAIL
+
+ [:name="LeftSE"]
+ expected: FAIL
+
+ [:name="RightSE"]
+ expected: FAIL
+
+ [:name="LeftmostSE"]
+ expected: FAIL
+
+ [:name="RightmostSE"]
+ expected: FAIL
+
+ [:name="MiddleSE"]
+ expected: FAIL
+
+ [:name="ShortCircuit_And_LhsOnly"]
+ expected: FAIL
+
+ [:name="ShortCircuit_And_LhsAndRhs"]
+ expected: FAIL
+
+ [:name="ShortCircuit_Or_LhsOnly"]
+ expected: FAIL
+
+ [:name="ShortCircuit_Or_LhsAndRhs"]
+ expected: FAIL
+
+ [:name="NoShortCircuit_And"]
+ expected: FAIL
+
+ [:name="NoShortCircuit_Or"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,evaluation_order:type_constructor:*]
+ [:name="Struct"]
+ expected: FAIL
+
+ [:name="Array1D"]
+ expected: FAIL
+
+ [:name="Array2D"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/31/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/31/cts.https.html.ini
new file mode 100644
index 0000000000..5be380152b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/31/cts.https.html.ini
@@ -0,0 +1,1224 @@
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:addition:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,i32_arithmetic:division:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:less_equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:greater_equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:subtraction:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:less_than:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_int:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,bool_logical:not_equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,i32_arithmetic:multiplication:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:division:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_arithmetic:remainder:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:greater_than:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,i32_arithmetic:subtraction:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication_scalar_vector:*]
+ [:inputSource="const";vectorize_rhs=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize_rhs=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize_rhs=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_rhs=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_rhs=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_rhs=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_rhs=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_rhs=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_rhs=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_rhs=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_rhs=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_rhs=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,i32_arithmetic:addition:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_arithmetic:division:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:remainder:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_arithmetic:multiplication:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication_vector_scalar:*]
+ [:inputSource="const";vectorize_lhs=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize_lhs=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize_lhs=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_lhs=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_lhs=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize_lhs=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_lhs=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_lhs=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize_lhs=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_lhs=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_lhs=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize_lhs=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,i32_arithmetic:remainder:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_logical:not_equals:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_arithmetic:subtraction:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,binary,f32_arithmetic:addition:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/32/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/32/cts.https.html.ini
new file mode 100644
index 0000000000..27c23a12cc
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/32/cts.https.html.ini
@@ -0,0 +1,1203 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acos:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asin:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acos:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acosh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acos:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acosh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asin:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asinh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,any:bool:*]
+ [:inputSource="const";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,abs:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asin:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asinh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,all:bool:*]
+ [:inputSource="const";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";overload="vec4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,acosh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,arrayLength:array:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,asinh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/33/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/33/cts.https.html.ini
new file mode 100644
index 0000000000..141f0584d8
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/33/cts.https.html.ini
@@ -0,0 +1,459 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atanh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atanh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicStore:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atan2:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:exchange:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicMin:min:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:exchange:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atanh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicOr:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicMax:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:load:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:add:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:and:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicXor:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicOr:or:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicSub:sub:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicMax:max:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicSub:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicMin:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicStore:store:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/34/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/34/cts.https.html.ini
new file mode 100644
index 0000000000..011252a313
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/34/cts.https.html.ini
@@ -0,0 +1,1104 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cosh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cross:abstract_float:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cross:f32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cosh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cos:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cos:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countOneBits:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,atomicXor:xor:*]
+ [:SC="storage";T="i32"]
+ expected: FAIL
+
+ [:SC="storage";T="u32"]
+ expected: FAIL
+
+ [:SC="uniform";T="i32"]
+ expected: FAIL
+
+ [:SC="uniform";T="u32"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ceil:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cross:f16:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cosh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countOneBits:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_int:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,cos:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ceil:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ceil:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,clamp:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/35/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/35/cts.https.html.ini
new file mode 100644
index 0000000000..3fff677044
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/35/cts.https.html.ini
@@ -0,0 +1,780 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:f16:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,determinant:abstract_float:*]
+ [:inputSource="const";dimension=2]
+ expected: FAIL
+
+ [:inputSource="const";dimension=3]
+ expected: FAIL
+
+ [:inputSource="const";dimension=4]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=2]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=3]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,determinant:f16:*]
+ [:inputSource="const";dimension=2]
+ expected: FAIL
+
+ [:inputSource="const";dimension=3]
+ expected: FAIL
+
+ [:inputSource="const";dimension=4]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=2]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=3]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_float:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,degrees:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_int:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:f32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,degrees:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdxCoarse:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:u32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdx:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,determinant:f32:*]
+ [:inputSource="const";dimension=2]
+ expected: FAIL
+
+ [:inputSource="const";dimension=3]
+ expected: FAIL
+
+ [:inputSource="const";dimension=4]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=2]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=3]
+ expected: FAIL
+
+ [:inputSource="uniform";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";dimension=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";dimension=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdxFine:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,degrees:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dot:i32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdyCoarse:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdy:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/36/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/36/cts.https.html.ini
new file mode 100644
index 0000000000..bf2deda993
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/36/cts.https.html.ini
@@ -0,0 +1,1116 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,dpdyFine:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fma:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,faceForward:abstract_float:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp2:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp2:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,extractBits:i32:*]
+ [:inputSource="const";width=1]
+ expected: FAIL
+
+ [:inputSource="const";width=2]
+ expected: FAIL
+
+ [:inputSource="const";width=3]
+ expected: FAIL
+
+ [:inputSource="const";width=4]
+ expected: FAIL
+
+ [:inputSource="uniform";width=1]
+ expected: FAIL
+
+ [:inputSource="uniform";width=2]
+ expected: FAIL
+
+ [:inputSource="uniform";width=3]
+ expected: FAIL
+
+ [:inputSource="uniform";width=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=1]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=1]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fma:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,floor:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fract:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,extractBits:u32:*]
+ [:inputSource="const";width=1]
+ expected: FAIL
+
+ [:inputSource="const";width=2]
+ expected: FAIL
+
+ [:inputSource="const";width=3]
+ expected: FAIL
+
+ [:inputSource="const";width=4]
+ expected: FAIL
+
+ [:inputSource="uniform";width=1]
+ expected: FAIL
+
+ [:inputSource="uniform";width=2]
+ expected: FAIL
+
+ [:inputSource="uniform";width=3]
+ expected: FAIL
+
+ [:inputSource="uniform";width=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=1]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";width=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=1]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";width=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,floor:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,exp2:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,faceForward:f16:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fma:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,floor:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/37/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/37/cts.https.html.ini
new file mode 100644
index 0000000000..2ff203823d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/37/cts.https.html.ini
@@ -0,0 +1,1056 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f32:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fwidthFine:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ldexp:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fract:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ldexp:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:f32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fwidthCoarse:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f16:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,ldexp:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fwidth:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f16:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,fract:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f32:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,insertBits:integer:*]
+ [:inputSource="const";signed=false;width=1]
+ expected: FAIL
+
+ [:inputSource="const";signed=false;width=2]
+ expected: FAIL
+
+ [:inputSource="const";signed=false;width=3]
+ expected: FAIL
+
+ [:inputSource="const";signed=false;width=4]
+ expected: FAIL
+
+ [:inputSource="const";signed=true;width=1]
+ expected: FAIL
+
+ [:inputSource="const";signed=true;width=2]
+ expected: FAIL
+
+ [:inputSource="const";signed=true;width=3]
+ expected: FAIL
+
+ [:inputSource="const";signed=true;width=4]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=false;width=1]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=false;width=2]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=false;width=3]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=false;width=4]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=true;width=1]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=true;width=2]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=true;width=3]
+ expected: FAIL
+
+ [:inputSource="uniform";signed=true;width=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=false;width=1]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=false;width=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=false;width=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=false;width=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=true;width=1]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=true;width=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=true;width=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";signed=true;width=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=false;width=1]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=false;width=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=false;width=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=false;width=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=true;width=1]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=true;width=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=true;width=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";signed=true;width=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/38/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/38/cts.https.html.ini
new file mode 100644
index 0000000000..84fa6bab13
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/38/cts.https.html.ini
@@ -0,0 +1,1068 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log2:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec2_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log2:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_abstract_float:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:matching_f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:monmatching_f16:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec2_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:matching_abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:abstract_int:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:matching_f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,log2:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,max:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,min:abstract_int:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_f32:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/39/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/39/cts.https.html.ini
new file mode 100644
index 0000000000..4a19a6e50a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/39/cts.https.html.ini
@@ -0,0 +1,528 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec4_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec3_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec2_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pack4x8unorm:pack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec4_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pow:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,normalize:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec4_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pack2x16float:pack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec4_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pow:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec3_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pow:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pack2x16snorm:pack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,normalize:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pack4x8snorm:pack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec2_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_whole:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec3_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,pack2x16unorm:pack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec3_fract:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/4/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/4/cts.https.html.ini
new file mode 100644
index 0000000000..2ccd2b0276
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/4/cts.https.html.ini
@@ -0,0 +1,1488 @@
+[cts.https.html?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel_order:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw:*]
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-pass-encoder"};write={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-pass-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-pass-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-bundle-encoder"};write={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-bundle-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";read={"op":"sample","in":"render-bundle-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2b-copy","in":"command-encoder"};write={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"t2t-copy","in":"command-encoder"};write={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"render-pass-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"render-pass-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"render-bundle-encoder"};write={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";read={"op":"sample","in":"render-bundle-encoder"};write={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="pass";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="dispatch";read={"op":"sample","in":"compute-pass-encoder"};write={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,pipeline,default_layout:incompatible_with_explicit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,pipeline,default_layout:getBindGroupLayout_js_object:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,texture,same_subresource:ww:*]
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"write-texture","in":"queue"};second={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-store","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-pass-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-pass-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-pass-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-bundle-encoder"};second={"op":"write-texture","in":"queue"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-bundle-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";first={"op":"storage","in":"render-bundle-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"b2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"t2t-copy","in":"command-encoder"};second={"op":"storage","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-store","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-store","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-store","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-store","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-store","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"attachment-resolve","in":"command-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"attachment-store","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"attachment-resolve","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"render-pass-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"render-pass-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"render-bundle-encoder"};second={"op":"b2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";first={"op":"storage","in":"render-bundle-encoder"};second={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="pass";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="dispatch";first={"op":"storage","in":"compute-pass-encoder"};second={"op":"storage","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,onSubmittedWorkDone:without_work:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,onSubmittedWorkDone:many,serial:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:rw:*]
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,queue,writeBuffer:multiple_writes_at_different_offsets_and_sizes:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,onSubmittedWorkDone:with_work:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_pass:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_dispatches_in_the_same_compute_pass:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,pipeline,default_layout:layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:wr:*]
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="write-buffer";writeContext="queue"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="queue-op";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2b-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="b2t-copy";readContext="command-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-bundle-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="storage-read";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-vertex";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="input-indirect-index";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-pass-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="b2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="command-buffer";readOp="constant-uniform";readContext="render-bundle-encoder";writeOp="t2b-copy";writeContext="command-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="render-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="pass";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="input-indirect-dispatch";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+ [:boundary="dispatch";readOp="storage-read";readContext="compute-pass-encoder";writeOp="storage";writeContext="compute-pass-encoder"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,reflection:buffer_reflection_attributes:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,reflection:texture_reflection_attributes:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_resolve:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:ww:*]
+ [:boundary="queue-op";writeOps=["write-buffer","write-buffer"\];contexts=["queue","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","b2b-copy"\];contexts=["queue","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","t2b-copy"\];contexts=["queue","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["write-buffer","storage"\];contexts=["queue","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","write-buffer"\];contexts=["command-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","write-buffer"\];contexts=["command-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["compute-pass-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["render-pass-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","write-buffer"\];contexts=["render-bundle-encoder","queue"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","b2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","t2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="queue-op";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","b2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","t2b-copy"\];contexts=["command-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["b2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["t2b-copy","storage"\];contexts=["command-encoder","render-bundle-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","b2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["compute-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["render-pass-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","t2b-copy"\];contexts=["render-bundle-encoder","command-encoder"\]]
+ expected: FAIL
+
+ [:boundary="command-buffer";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="pass";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+ [:boundary="dispatch";writeOps=["storage","storage"\];contexts=["compute-pass-encoder","compute-pass-encoder"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_draws_in_one_render_bundle:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,queue,writeBuffer:array_types:*]
+ [:arrayType="Uint8Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Uint8Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Uint16Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Uint16Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Uint32Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Uint32Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Int8Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Int8Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Int16Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Int16Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Int32Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Int32Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Float32Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Float32Array";useArrayBuffer=true]
+ expected: FAIL
+
+ [:arrayType="Float64Array";useArrayBuffer=false]
+ expected: FAIL
+
+ [:arrayType="Float64Array";useArrayBuffer=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_store:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,texture,same_subresource:wr:*]
+ [:boundary="queue-op";write={"op":"write-texture","in":"queue"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"write-texture","in":"queue"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"write-texture","in":"queue"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"write-texture","in":"queue"};read={"op":"sample","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"write-texture","in":"queue"};read={"op":"sample","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-store","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-store","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-store","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"render-pass-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"render-pass-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"render-bundle-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="queue-op";write={"op":"storage","in":"render-bundle-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"b2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"t2t-copy","in":"command-encoder"};read={"op":"sample","in":"render-bundle-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-store","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-store","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-store","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"attachment-resolve","in":"command-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"render-pass-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"render-pass-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"render-bundle-encoder"};read={"op":"t2b-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="command-buffer";write={"op":"storage","in":"render-bundle-encoder"};read={"op":"t2t-copy","in":"command-encoder"}]
+ expected: FAIL
+
+ [:boundary="pass";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+ [:boundary="dispatch";write={"op":"storage","in":"compute-pass-encoder"};read={"op":"sample","in":"compute-pass-encoder"}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_bundle:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_dispatches_in_one_compute_pass:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/40/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/40/cts.https.html.ini
new file mode 100644
index 0000000000..3a95497f99
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/40/cts.https.html.ini
@@ -0,0 +1,1224 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sign:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reverseBits:i32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,saturate:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,quantizeToF16:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,refract:abstract_float:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reflect:abstract_float:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,refract:f16:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,radians:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reverseBits:u32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,radians:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,round:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec3:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,select:vector:*]
+ [:inputSource="const";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec4:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,round:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,select:scalar:*]
+ [:inputSource="const";component="b";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="const";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="uniform";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_r";component="u";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="b";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="f";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="i";overload="vec4"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="scalar"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec2"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec3"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";component="u";overload="vec4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reflect:f16:*]
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec2:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,saturate:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,round:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,radians:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,saturate:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/41/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/41/cts.https.html.ini
new file mode 100644
index 0000000000..fc989f1483
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/41/cts.https.html.ini
@@ -0,0 +1,1164 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,step:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sin:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,step:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sin:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:stage:*]
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sinh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tanh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tan:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tan:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sinh:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,step:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,smoothstep:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tanh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sign:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tan:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sign:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sqrt:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sqrt:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sqrt:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sin:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,sinh:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:barrier:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,tanh:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/42/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/42/cts.https.html.ini
new file mode 100644
index 0000000000..15f81a6282
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/42/cts.https.html.ini
@@ -0,0 +1,849 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:depth:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:sampled:*]
+ [:texture_type="texture_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_cube_array"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_2d:*]
+ [:C="i32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level="numlevels"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureDimension:external:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_1d:*]
+ [:C="i32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:external:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureDimension:depth:*]
+ [:texture_type="texture_depth_2d"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube_array"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_multisampled_2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:arrayed:*]
+ [:texture_type="texture_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_2d_array"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureDimension:sampled:*]
+ [:texture_type="texture_1d"]
+ expected: FAIL
+
+ [:texture_type="texture_2d"]
+ expected: FAIL
+
+ [:texture_type="texture_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_3d"]
+ expected: FAIL
+
+ [:texture_type="texture_cube"]
+ expected: FAIL
+
+ [:texture_type="texture_cube_array"]
+ expected: FAIL
+
+ [:texture_type="texture_multisampled_2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:arrayed:*]
+ [:texture_type="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube_array"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:multisampled:*]
+ [:texture_type="texture_multisampled_2d"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_multisampled_2d"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureDimension:storage:*]
+ [:texel_format="rgba8unorm"]
+ expected: FAIL
+
+ [:texel_format="rgba8snorm"]
+ expected: FAIL
+
+ [:texel_format="rgba8uint"]
+ expected: FAIL
+
+ [:texel_format="rgba8sint"]
+ expected: FAIL
+
+ [:texel_format="rgba16uint"]
+ expected: FAIL
+
+ [:texel_format="rgba16sint"]
+ expected: FAIL
+
+ [:texel_format="rgba16float"]
+ expected: FAIL
+
+ [:texel_format="r32uint"]
+ expected: FAIL
+
+ [:texel_format="r32sint"]
+ expected: FAIL
+
+ [:texel_format="r32float"]
+ expected: FAIL
+
+ [:texel_format="rg32uint"]
+ expected: FAIL
+
+ [:texel_format="rg32sint"]
+ expected: FAIL
+
+ [:texel_format="rg32float"]
+ expected: FAIL
+
+ [:texel_format="rgba32uint"]
+ expected: FAIL
+
+ [:texel_format="rgba32sint"]
+ expected: FAIL
+
+ [:texel_format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_3d:*]
+ [:C="i32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="y-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="z-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="i32";coords="z-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="in-bounds";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="x-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="y-max-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="z-min-boundary";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-wrap";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-wrap";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-wrap";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-wrap";level="numlevels"]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-boundary";level=-1]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-boundary";level=0]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-boundary";level="numlevels-1"]
+ expected: FAIL
+
+ [:C="u32";coords="z-max-boundary";level="numlevels"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/43/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/43/cts.https.html.ini
new file mode 100644
index 0000000000..27132c2430
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/43/cts.https.html.ini
@@ -0,0 +1,189 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_1d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:control_flow:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:depth:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:control_flow:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:sampled:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_3d_coords:*]
+ [:texture_type="texture_3d"]
+ expected: FAIL
+
+ [:texture_type="texture_cube"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:depth:*]
+ [:texture_type="texture_depth_2d"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube_array"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:storage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:control_flow:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:sampled:*]
+ [:texture_type="texture_1d"]
+ expected: FAIL
+
+ [:texture_type="texture_2d"]
+ expected: FAIL
+
+ [:texture_type="texture_2d_array"]
+ expected: FAIL
+
+ [:texture_type="texture_3d"]
+ expected: FAIL
+
+ [:texture_type="texture_cube"]
+ expected: FAIL
+
+ [:texture_type="texture_cube_array%60"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_3d_coords:*]
+ [:texture_type="texture_3d"]
+ expected: FAIL
+
+ [:texture_type="texture_cube"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/44/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/44/cts.https.html.ini
new file mode 100644
index 0000000000..1e02d5ea43
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/44/cts.https.html.ini
@@ -0,0 +1,426 @@
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_1d_coords:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_2d_coords:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:stage:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_3d_coords:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_3d_coords:*]
+ [:texture_type="texture_depth_cube"]
+ expected: FAIL
+
+ [:texture_type="texture_depth_cube_array"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:control_flow:*]
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_array_2d_coords:*]
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_3d_coords:*]
+ [:texture_type="texture_3d"]
+ expected: FAIL
+
+ [:texture_type="texture_cube"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,transpose:abstract_float:*]
+ [:inputSource="const";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:3d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_array_2d_coords:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_3d_coords:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/45/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/45/cts.https.html.ini
new file mode 100644
index 0000000000..9c681ac1ea
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/45/cts.https.html.ini
@@ -0,0 +1,738 @@
+[cts.https.html?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_load:*]
+ [:memType="non_atomic_storage"]
+ expected: FAIL
+
+ [:memType="non_atomic_workgroup"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,coherence:corw1:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,transpose:f16:*]
+ [:inputSource="const";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_load_store:*]
+ [:memType="non_atomic_storage"]
+ expected: FAIL
+
+ [:memType="non_atomic_workgroup"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,unpack2x16float:unpack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,trunc:f32:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:message_passing:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,transpose:f32:*]
+ [:inputSource="const";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="const";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="uniform";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";rows=4;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=2;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=3;cols=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";rows=4;cols=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,unary,bool_logical:negation:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,atomicity:atomicity:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,unpack2x16snorm:unpack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:stage:*]
+ [:stage="vertex"]
+ expected: FAIL
+
+ [:stage="fragment"]
+ expected: FAIL
+
+ [:stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,trunc:f16:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,coherence:coww:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="inter_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_store:*]
+ [:memType="non_atomic_storage"]
+ expected: FAIL
+
+ [:memType="non_atomic_workgroup"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,unary,f32_arithmetic:negation:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,coherence:cowr:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="inter_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,coherence:corw2:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="inter_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:barrier:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,coherence:corr:*]
+ [:memType="atomic_storage";testType="inter_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="inter_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_workgroup";testType="intra_workgroup";extraFlags="rmw_variant"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,unary,i32_arithmetic:negation:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,unpack2x16unorm:unpack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,unpack4x8unorm:unpack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,trunc:abstract_float:*]
+ [:inputSource="const";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="const";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="uniform";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_r";vectorize=4]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize="_undef_"]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=2]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=3]
+ expected: FAIL
+
+ [:inputSource="storage_rw";vectorize=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,expression,call,builtin,unpack4x8snorm:unpack:*]
+ [:inputSource="const"]
+ expected: FAIL
+
+ [:inputSource="uniform"]
+ expected: FAIL
+
+ [:inputSource="storage_r"]
+ expected: FAIL
+
+ [:inputSource="storage_rw"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/46/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/46/cts.https.html.ini
new file mode 100644
index 0000000000..98aea2e684
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/46/cts.https.html.ini
@@ -0,0 +1,8169 @@
+[cts.https.html?q=webgpu:shader,validation,parse,builtin:parse:*]
+ [:builtin="%40builtin(position)"]
+ expected: FAIL
+
+ [:builtin="%40builtin(position,)"]
+ expected: FAIL
+
+ [:builtin="%40%20%5Cn%20builtin(position)"]
+ expected: FAIL
+
+ [:builtin="%40%2F%5E%20comment%20%5E%2Fbuiltin%2F%5E%20comment%20%5E%2F%5Cn%5Cn(%5Ct%2F%5Ecomment%5E%2Fposition%2F%5Ecomment%5E%2F)"]
+ expected: FAIL
+
+ [:builtin="%40abuiltin(position)"]
+ expected: FAIL
+
+ [:builtin="%40builtin"]
+ expected: FAIL
+
+ [:builtin="%40builtin()"]
+ expected: FAIL
+
+ [:builtin="%40builtin%20position"]
+ expected: FAIL
+
+ [:builtin="%40builtin%20position)"]
+ expected: FAIL
+
+ [:builtin="%40builtin(position"]
+ expected: FAIL
+
+ [:builtin="%40builtin(position,%20frag_depth)"]
+ expected: FAIL
+
+ [:builtin="%40builtin(identifier)"]
+ expected: FAIL
+
+ [:builtin="%40builtin(2)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:array_of_vec3:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,align:align_required_alignment:*]
+ [:address_space="storage";align=1;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=1;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=2;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align="alignment";type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"i32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"u32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"f32","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"atomic%3Ci32%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec2%3Ci32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec3%3Cu32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x2%3Cf32%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x3%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x4%3Cf32%3E","storage":16,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"array%3Cvec2%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"array%3Cvec4%3Ci32%3E,%202%3E","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="uniform";align=32;type={"name":"S","storage":8,"uniform":16}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=1;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=2;type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat2x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat3x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align="alignment";type={"name":"mat4x4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"f16","storage":2,"uniform":2}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"vec4%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x2%3Cf16%3E","storage":4,"uniform":4}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat2x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat3x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+ [:address_space="storage";align=32;type={"name":"mat4x3%3Cf16%3E","storage":8,"uniform":8}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:struct_nested:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:2_plus_2_write:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_non_entry_point_function:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:vec3:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:*]
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="vertexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=false;indirect=true;drawCallTestParameter="firstVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=false;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="baseVertex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="vertexCountInIndexBuffer";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="indexCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="instanceCount";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x2";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x3";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=0;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=false;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=false;errorScale=1000000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=0]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=4]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=100]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=10000]
+ expected: FAIL
+
+ [:indexed=true;indirect=true;drawCallTestParameter="firstIndex";type="float32x4";additionalBuffers=4;partialLastNumber=true;offsetVertexBuffer=true;errorScale=1000000]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:store:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:*]
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,1\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,32,1\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[64,1,1\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,48\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,47,1\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[33,1,1\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[1,1,63\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[8,8,2\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=30]
+ expected: FAIL
+
+ [:storageClass="workgroup";workgroupSize=[7,7,3\];batch__=31]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="private";workgroupSize=[1,1,1\];batch__=29]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=0]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=1]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=2]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=3]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=4]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=5]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=6]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=7]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=8]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=9]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=10]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=11]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=12]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=13]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=14]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=15]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=16]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=17]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=18]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=19]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=20]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=21]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=22]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=23]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=24]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=25]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=26]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=27]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=28]
+ expected: FAIL
+
+ [:storageClass="function";workgroupSize=[1,1,1\];batch__=29]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,blankspace:null_characters:*]
+ [:contains_null=true;placement="comment"]
+ expected: FAIL
+
+ [:contains_null=true;placement="delimiter"]
+ expected: FAIL
+
+ [:contains_null=true;placement="eol"]
+ expected: FAIL
+
+ [:contains_null=false;placement="comment"]
+ expected: FAIL
+
+ [:contains_null=false;placement="delimiter"]
+ expected: FAIL
+
+ [:contains_null=false;placement="eol"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:store_buffer:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:array_of_struct:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:load_buffer:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,shader_io,compute_builtins:inputs:*]
+ [:method="param";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="param";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="param";dispatch="direct";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="param";dispatch="direct";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+ [:method="param";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="param";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="param";dispatch="indirect";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="param";dispatch="indirect";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+ [:method="struct";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="struct";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="struct";dispatch="direct";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="struct";dispatch="direct";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+ [:method="struct";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="struct";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="struct";dispatch="indirect";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="struct";dispatch="indirect";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="direct";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="direct";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="direct";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="indirect";groupSize={"x":1,"y":1,"z":1};numGroups={"x":8,"y":4,"z":2}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="indirect";groupSize={"x":8,"y":4,"z":2};numGroups={"x":1,"y":1,"z":1}]
+ expected: FAIL
+
+ [:method="mixed";dispatch="indirect";groupSize={"x":3,"y":7,"z":5};numGroups={"x":13,"y":9,"z":11}]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,robust_access:linear_memory:*]
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=false;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read";access="read";dynamicOffset=true;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=false;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="read";dynamicOffset=true;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=false;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="storage";storageMode="read_write";access="write";dynamicOffset=true;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=false;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="uniform";access="read";dynamicOffset=true;containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="read";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="private";access="write";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="read";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="function";access="write";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="read";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="none";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="module-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="array";shadowingMode="function-scope";isAtomic=true]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="matrix";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="matrix";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="matrix";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="vector";shadowingMode="none";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="vector";shadowingMode="module-scope";isAtomic=false]
+ expected: FAIL
+
+ [:storageClass="workgroup";access="write";containerType="vector";shadowingMode="function-scope";isAtomic=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:struct_explicit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,align:align_parsing:*]
+ [:align=""]
+ expected: FAIL
+
+ [:align="%40align(1)"]
+ expected: FAIL
+
+ [:align="%40align(4)"]
+ expected: FAIL
+
+ [:align="%40align(4i)"]
+ expected: FAIL
+
+ [:align="%40align(4u)"]
+ expected: FAIL
+
+ [:align="%40align(0x4)"]
+ expected: FAIL
+
+ [:align="%40align(4,)"]
+ expected: FAIL
+
+ [:align="%40align(u_val)"]
+ expected: FAIL
+
+ [:align="%40align(i_val)"]
+ expected: FAIL
+
+ [:align="%40align(i_val%20%2B%204%20-%206)"]
+ expected: FAIL
+
+ [:align="%40align(1073741824)"]
+ expected: FAIL
+
+ [:align="%40%5Ctalign%5Ct(4)"]
+ expected: FAIL
+
+ [:align="%40%2F%5Ecomment%5E%2Falign%2F%5Ecomment%5E%2F(4)"]
+ expected: FAIL
+
+ [:align="%40malign(4)"]
+ expected: FAIL
+
+ [:align="%40align()"]
+ expected: FAIL
+
+ [:align="%40align%204)"]
+ expected: FAIL
+
+ [:align="%40align(4"]
+ expected: FAIL
+
+ [:align="%40align(4,%202)"]
+ expected: FAIL
+
+ [:align="%40align(3)"]
+ expected: FAIL
+
+ [:align="%40align(f_val)"]
+ expected: FAIL
+
+ [:align="%40align(1.0)"]
+ expected: FAIL
+
+ [:align="%40align(4f)"]
+ expected: FAIL
+
+ [:align="%40align(4h)"]
+ expected: FAIL
+
+ [:align="%40align"]
+ expected: FAIL
+
+ [:align="%40align(0)"]
+ expected: FAIL
+
+ [:align="%40align(-4)"]
+ expected: FAIL
+
+ [:align="%40align(2147483646)"]
+ expected: FAIL
+
+ [:align="%40align(2147483648)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,memory_model,weak:read:*]
+ [:memType="atomic_workgroup"]
+ expected: FAIL
+
+ [:memType="atomic_storage"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,blankspace:blankspace:*]
+ [:blankspace=["%20","space"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Ct","horizontal_tab"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cn","line_feed"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cu000b","vertical_tab"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cf","form_feed"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cr","carriage_return"\]]
+ expected: FAIL
+
+ [:blankspace=["%C2%85","next_line"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%8E","left_to_right_mark"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%8F","right_to_left_mark"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%A8","line_separator"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%A9","paragraph_separator"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,shader_io,shared_structs:shared_between_stages:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,comments:comments:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,comments:line_comment_eof:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,execution,padding:struct_implicit:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/47/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/47/cts.https.html.ini
new file mode 100644
index 0000000000..a653eeebb5
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/47/cts.https.html.ini
@@ -0,0 +1,1539 @@
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_let_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:u32:*]
+ [:val="0x123"]
+ expected: FAIL
+
+ [:val="123"]
+ expected: FAIL
+
+ [:val="0"]
+ expected: FAIL
+
+ [:val="0x3f"]
+ expected: FAIL
+
+ [:val="2147483647"]
+ expected: FAIL
+
+ [:val="42u"]
+ expected: FAIL
+
+ [:val="0u"]
+ expected: FAIL
+
+ [:val="4294967295u"]
+ expected: FAIL
+
+ [:val="4294967295"]
+ expected: FAIL
+
+ [:val="-0x123"]
+ expected: FAIL
+
+ [:val="-123"]
+ expected: FAIL
+
+ [:val="-0x3f"]
+ expected: FAIL
+
+ [:val="-2147483647"]
+ expected: FAIL
+
+ [:val="-2147483648"]
+ expected: FAIL
+
+ [:val="94i"]
+ expected: FAIL
+
+ [:val="2147483647i"]
+ expected: FAIL
+
+ [:val="-2147483647i"]
+ expected: FAIL
+
+ [:val="i32(-2147483648)"]
+ expected: FAIL
+
+ [:val="4294967296"]
+ expected: FAIL
+
+ [:val="4294967296u"]
+ expected: FAIL
+
+ [:val="-1"]
+ expected: FAIL
+
+ [:val="1.0"]
+ expected: FAIL
+
+ [:val="1.0f"]
+ expected: FAIL
+
+ [:val="1.0h"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_return:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,identifiers:identifiers:*]
+ [:ident="foo"]
+ expected: FAIL
+
+ [:ident="Foo"]
+ expected: FAIL
+
+ [:ident="FOO"]
+ expected: FAIL
+
+ [:ident="_0"]
+ expected: FAIL
+
+ [:ident="_foo0"]
+ expected: FAIL
+
+ [:ident="_0foo"]
+ expected: FAIL
+
+ [:ident="foo__0"]
+ expected: FAIL
+
+ [:ident="%CE%94%CE%AD%CE%BB%CF%84%CE%B1"]
+ expected: FAIL
+
+ [:ident="r%C3%A9flexion"]
+ expected: FAIL
+
+ [:ident="%D0%9A%D1%8B%D0%B7%D1%8B%D0%BB"]
+ expected: FAIL
+
+ [:ident="%F0%90%B0%93%F0%90%B0%8F%F0%90%B0%87"]
+ expected: FAIL
+
+ [:ident="%E6%9C%9D%E7%84%BC%E3%81%91"]
+ expected: FAIL
+
+ [:ident="%D8%B3%D9%84%D8%A7%D9%85"]
+ expected: FAIL
+
+ [:ident="%EA%B2%80%EC%A0%95"]
+ expected: FAIL
+
+ [:ident="%D7%A9%D6%B8%D7%81%D7%9C%D7%95%D6%B9%D7%9D"]
+ expected: FAIL
+
+ [:ident="%E0%A4%97%E0%A5%81%E0%A4%B2%E0%A4%BE%E0%A4%AC%E0%A5%80"]
+ expected: FAIL
+
+ [:ident="%D6%83%D5%AB%D6%80%D5%B8%D6%82%D5%A6"]
+ expected: FAIL
+
+ [:ident="_"]
+ expected: FAIL
+
+ [:ident="__"]
+ expected: FAIL
+
+ [:ident="__foo"]
+ expected: FAIL
+
+ [:ident="0foo"]
+ expected: FAIL
+
+ [:ident="foo.bar"]
+ expected: FAIL
+
+ [:ident="foo-bar"]
+ expected: FAIL
+
+ [:ident="foo%2Bbar"]
+ expected: FAIL
+
+ [:ident="foo%23bar"]
+ expected: FAIL
+
+ [:ident="foo!bar"]
+ expected: FAIL
+
+ [:ident="foo%5C%5Cbar"]
+ expected: FAIL
+
+ [:ident="foo%2Fbar"]
+ expected: FAIL
+
+ [:ident="foo,bar"]
+ expected: FAIL
+
+ [:ident="foo%40bar"]
+ expected: FAIL
+
+ [:ident="foo::bar"]
+ expected: FAIL
+
+ [:ident="array"]
+ expected: FAIL
+
+ [:ident="atomic"]
+ expected: FAIL
+
+ [:ident="bool"]
+ expected: FAIL
+
+ [:ident="f32"]
+ expected: FAIL
+
+ [:ident="f16"]
+ expected: FAIL
+
+ [:ident="i32"]
+ expected: FAIL
+
+ [:ident="mat2x2"]
+ expected: FAIL
+
+ [:ident="mat2x3"]
+ expected: FAIL
+
+ [:ident="mat2x4"]
+ expected: FAIL
+
+ [:ident="mat3x2"]
+ expected: FAIL
+
+ [:ident="mat3x3"]
+ expected: FAIL
+
+ [:ident="mat3x4"]
+ expected: FAIL
+
+ [:ident="mat4x2"]
+ expected: FAIL
+
+ [:ident="mat4x3"]
+ expected: FAIL
+
+ [:ident="mat4x4"]
+ expected: FAIL
+
+ [:ident="ptr"]
+ expected: FAIL
+
+ [:ident="sampler"]
+ expected: FAIL
+
+ [:ident="sampler_comparison"]
+ expected: FAIL
+
+ [:ident="texture_1d"]
+ expected: FAIL
+
+ [:ident="texture_2d"]
+ expected: FAIL
+
+ [:ident="texture_2d_array"]
+ expected: FAIL
+
+ [:ident="texture_3d"]
+ expected: FAIL
+
+ [:ident="texture_cube"]
+ expected: FAIL
+
+ [:ident="texture_cube_array"]
+ expected: FAIL
+
+ [:ident="texture_multisampled_2d"]
+ expected: FAIL
+
+ [:ident="texture_storage_1d"]
+ expected: FAIL
+
+ [:ident="texture_storage_2d"]
+ expected: FAIL
+
+ [:ident="texture_storage_2d_array"]
+ expected: FAIL
+
+ [:ident="texture_storage_3d"]
+ expected: FAIL
+
+ [:ident="texture_depth_2d"]
+ expected: FAIL
+
+ [:ident="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:ident="texture_depth_cube"]
+ expected: FAIL
+
+ [:ident="texture_depth_cube_array"]
+ expected: FAIL
+
+ [:ident="texture_depth_multisampled_2d"]
+ expected: FAIL
+
+ [:ident="u32"]
+ expected: FAIL
+
+ [:ident="vec2"]
+ expected: FAIL
+
+ [:ident="vec3"]
+ expected: FAIL
+
+ [:ident="vec4"]
+ expected: FAIL
+
+ [:ident="bitcast"]
+ expected: FAIL
+
+ [:ident="break"]
+ expected: FAIL
+
+ [:ident="case"]
+ expected: FAIL
+
+ [:ident="const"]
+ expected: FAIL
+
+ [:ident="continue"]
+ expected: FAIL
+
+ [:ident="continuing"]
+ expected: FAIL
+
+ [:ident="default"]
+ expected: FAIL
+
+ [:ident="discard"]
+ expected: FAIL
+
+ [:ident="else"]
+ expected: FAIL
+
+ [:ident="enable"]
+ expected: FAIL
+
+ [:ident="false"]
+ expected: FAIL
+
+ [:ident="fn"]
+ expected: FAIL
+
+ [:ident="for"]
+ expected: FAIL
+
+ [:ident="if"]
+ expected: FAIL
+
+ [:ident="let"]
+ expected: FAIL
+
+ [:ident="loop"]
+ expected: FAIL
+
+ [:ident="override"]
+ expected: FAIL
+
+ [:ident="return"]
+ expected: FAIL
+
+ [:ident="static_assert"]
+ expected: FAIL
+
+ [:ident="struct"]
+ expected: FAIL
+
+ [:ident="switch"]
+ expected: FAIL
+
+ [:ident="true"]
+ expected: FAIL
+
+ [:ident="type"]
+ expected: FAIL
+
+ [:ident="var"]
+ expected: FAIL
+
+ [:ident="while"]
+ expected: FAIL
+
+ [:ident="CompileShader"]
+ expected: FAIL
+
+ [:ident="ComputeShader"]
+ expected: FAIL
+
+ [:ident="DomainShader"]
+ expected: FAIL
+
+ [:ident="GeometryShader"]
+ expected: FAIL
+
+ [:ident="Hullshader"]
+ expected: FAIL
+
+ [:ident="NULL"]
+ expected: FAIL
+
+ [:ident="Self"]
+ expected: FAIL
+
+ [:ident="abstract"]
+ expected: FAIL
+
+ [:ident="active"]
+ expected: FAIL
+
+ [:ident="alignas"]
+ expected: FAIL
+
+ [:ident="alignof"]
+ expected: FAIL
+
+ [:ident="as"]
+ expected: FAIL
+
+ [:ident="asm"]
+ expected: FAIL
+
+ [:ident="asm_fragment"]
+ expected: FAIL
+
+ [:ident="async"]
+ expected: FAIL
+
+ [:ident="attribute"]
+ expected: FAIL
+
+ [:ident="auto"]
+ expected: FAIL
+
+ [:ident="await"]
+ expected: FAIL
+
+ [:ident="become"]
+ expected: FAIL
+
+ [:ident="binding_array"]
+ expected: FAIL
+
+ [:ident="cast"]
+ expected: FAIL
+
+ [:ident="catch"]
+ expected: FAIL
+
+ [:ident="class"]
+ expected: FAIL
+
+ [:ident="co_await"]
+ expected: FAIL
+
+ [:ident="co_return"]
+ expected: FAIL
+
+ [:ident="co_yield"]
+ expected: FAIL
+
+ [:ident="coherent"]
+ expected: FAIL
+
+ [:ident="column_major"]
+ expected: FAIL
+
+ [:ident="common"]
+ expected: FAIL
+
+ [:ident="compile"]
+ expected: FAIL
+
+ [:ident="compile_fragment"]
+ expected: FAIL
+
+ [:ident="concept"]
+ expected: FAIL
+
+ [:ident="const_cast"]
+ expected: FAIL
+
+ [:ident="consteval"]
+ expected: FAIL
+
+ [:ident="constexpr"]
+ expected: FAIL
+
+ [:ident="constinit"]
+ expected: FAIL
+
+ [:ident="crate"]
+ expected: FAIL
+
+ [:ident="debugger"]
+ expected: FAIL
+
+ [:ident="decltype"]
+ expected: FAIL
+
+ [:ident="delete"]
+ expected: FAIL
+
+ [:ident="demote"]
+ expected: FAIL
+
+ [:ident="demote_to_helper"]
+ expected: FAIL
+
+ [:ident="do"]
+ expected: FAIL
+
+ [:ident="dynamic_cast"]
+ expected: FAIL
+
+ [:ident="enum"]
+ expected: FAIL
+
+ [:ident="explicit"]
+ expected: FAIL
+
+ [:ident="export"]
+ expected: FAIL
+
+ [:ident="extends"]
+ expected: FAIL
+
+ [:ident="extern"]
+ expected: FAIL
+
+ [:ident="external"]
+ expected: FAIL
+
+ [:ident="fallthrough"]
+ expected: FAIL
+
+ [:ident="filter"]
+ expected: FAIL
+
+ [:ident="final"]
+ expected: FAIL
+
+ [:ident="finally"]
+ expected: FAIL
+
+ [:ident="friend"]
+ expected: FAIL
+
+ [:ident="from"]
+ expected: FAIL
+
+ [:ident="fxgroup"]
+ expected: FAIL
+
+ [:ident="get"]
+ expected: FAIL
+
+ [:ident="goto"]
+ expected: FAIL
+
+ [:ident="groupshared"]
+ expected: FAIL
+
+ [:ident="handle"]
+ expected: FAIL
+
+ [:ident="highp"]
+ expected: FAIL
+
+ [:ident="impl"]
+ expected: FAIL
+
+ [:ident="implements"]
+ expected: FAIL
+
+ [:ident="import"]
+ expected: FAIL
+
+ [:ident="inline"]
+ expected: FAIL
+
+ [:ident="inout"]
+ expected: FAIL
+
+ [:ident="instanceof"]
+ expected: FAIL
+
+ [:ident="interface"]
+ expected: FAIL
+
+ [:ident="layout"]
+ expected: FAIL
+
+ [:ident="lowp"]
+ expected: FAIL
+
+ [:ident="macro"]
+ expected: FAIL
+
+ [:ident="macro_rules"]
+ expected: FAIL
+
+ [:ident="match"]
+ expected: FAIL
+
+ [:ident="mediump"]
+ expected: FAIL
+
+ [:ident="meta"]
+ expected: FAIL
+
+ [:ident="mod"]
+ expected: FAIL
+
+ [:ident="module"]
+ expected: FAIL
+
+ [:ident="move"]
+ expected: FAIL
+
+ [:ident="mut"]
+ expected: FAIL
+
+ [:ident="mutable"]
+ expected: FAIL
+
+ [:ident="namespace"]
+ expected: FAIL
+
+ [:ident="new"]
+ expected: FAIL
+
+ [:ident="nil"]
+ expected: FAIL
+
+ [:ident="noexcept"]
+ expected: FAIL
+
+ [:ident="noinline"]
+ expected: FAIL
+
+ [:ident="nointerpolation"]
+ expected: FAIL
+
+ [:ident="noperspective"]
+ expected: FAIL
+
+ [:ident="null"]
+ expected: FAIL
+
+ [:ident="nullptr"]
+ expected: FAIL
+
+ [:ident="of"]
+ expected: FAIL
+
+ [:ident="operator"]
+ expected: FAIL
+
+ [:ident="package"]
+ expected: FAIL
+
+ [:ident="packoffset"]
+ expected: FAIL
+
+ [:ident="partition"]
+ expected: FAIL
+
+ [:ident="pass"]
+ expected: FAIL
+
+ [:ident="patch"]
+ expected: FAIL
+
+ [:ident="pixelfragment"]
+ expected: FAIL
+
+ [:ident="precise"]
+ expected: FAIL
+
+ [:ident="precision"]
+ expected: FAIL
+
+ [:ident="premerge"]
+ expected: FAIL
+
+ [:ident="priv"]
+ expected: FAIL
+
+ [:ident="protected"]
+ expected: FAIL
+
+ [:ident="pub"]
+ expected: FAIL
+
+ [:ident="public"]
+ expected: FAIL
+
+ [:ident="readonly"]
+ expected: FAIL
+
+ [:ident="ref"]
+ expected: FAIL
+
+ [:ident="regardless"]
+ expected: FAIL
+
+ [:ident="register"]
+ expected: FAIL
+
+ [:ident="reinterpret_cast"]
+ expected: FAIL
+
+ [:ident="requires"]
+ expected: FAIL
+
+ [:ident="resource"]
+ expected: FAIL
+
+ [:ident="restrict"]
+ expected: FAIL
+
+ [:ident="self"]
+ expected: FAIL
+
+ [:ident="set"]
+ expected: FAIL
+
+ [:ident="shared"]
+ expected: FAIL
+
+ [:ident="signed"]
+ expected: FAIL
+
+ [:ident="sizeof"]
+ expected: FAIL
+
+ [:ident="smooth"]
+ expected: FAIL
+
+ [:ident="snorm"]
+ expected: FAIL
+
+ [:ident="static"]
+ expected: FAIL
+
+ [:ident="static_cast"]
+ expected: FAIL
+
+ [:ident="std"]
+ expected: FAIL
+
+ [:ident="subroutine"]
+ expected: FAIL
+
+ [:ident="super"]
+ expected: FAIL
+
+ [:ident="target"]
+ expected: FAIL
+
+ [:ident="template"]
+ expected: FAIL
+
+ [:ident="this"]
+ expected: FAIL
+
+ [:ident="thread_local"]
+ expected: FAIL
+
+ [:ident="throw"]
+ expected: FAIL
+
+ [:ident="trait"]
+ expected: FAIL
+
+ [:ident="try"]
+ expected: FAIL
+
+ [:ident="typedef"]
+ expected: FAIL
+
+ [:ident="typeid"]
+ expected: FAIL
+
+ [:ident="typename"]
+ expected: FAIL
+
+ [:ident="typeof"]
+ expected: FAIL
+
+ [:ident="union"]
+ expected: FAIL
+
+ [:ident="unless"]
+ expected: FAIL
+
+ [:ident="unorm"]
+ expected: FAIL
+
+ [:ident="unsafe"]
+ expected: FAIL
+
+ [:ident="unsized"]
+ expected: FAIL
+
+ [:ident="use"]
+ expected: FAIL
+
+ [:ident="using"]
+ expected: FAIL
+
+ [:ident="varying"]
+ expected: FAIL
+
+ [:ident="virtual"]
+ expected: FAIL
+
+ [:ident="volatile"]
+ expected: FAIL
+
+ [:ident="wgsl"]
+ expected: FAIL
+
+ [:ident="where"]
+ expected: FAIL
+
+ [:ident="with"]
+ expected: FAIL
+
+ [:ident="writeonly"]
+ expected: FAIL
+
+ [:ident="yield"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_fn_const_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,comments:line_comment_terminators:*]
+ [:blankspace=["%20","space"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Ct","tab"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cn","line_feed"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cu000b","vertical_tab"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cf","form_feed"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cr","carriage_return"\]]
+ expected: FAIL
+
+ [:blankspace=["%5Cr%5Cn","carriage_return_line_feed"\]]
+ expected: FAIL
+
+ [:blankspace=["%C2%85","next_line"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%A8","line_separator"\]]
+ expected: FAIL
+
+ [:blankspace=["%E2%80%A9","paragraph_separator"\]]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_type_alias_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_module_var_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:f32:*]
+ [:val="0f"]
+ expected: FAIL
+
+ [:val="0.0f"]
+ expected: FAIL
+
+ [:val="12.223f"]
+ expected: FAIL
+
+ [:val="12.f"]
+ expected: FAIL
+
+ [:val=".12f"]
+ expected: FAIL
+
+ [:val="2.4e%2B4f"]
+ expected: FAIL
+
+ [:val="2.4e-2f"]
+ expected: FAIL
+
+ [:val="2.e%2B4f"]
+ expected: FAIL
+
+ [:val="1e-4f"]
+ expected: FAIL
+
+ [:val="0x1P%2B4f"]
+ expected: FAIL
+
+ [:val="0.0"]
+ expected: FAIL
+
+ [:val=".0"]
+ expected: FAIL
+
+ [:val="12."]
+ expected: FAIL
+
+ [:val="00012."]
+ expected: FAIL
+
+ [:val=".12"]
+ expected: FAIL
+
+ [:val="1.2e2"]
+ expected: FAIL
+
+ [:val="1.2E2"]
+ expected: FAIL
+
+ [:val="1.2e%2B2"]
+ expected: FAIL
+
+ [:val="2.4e-2"]
+ expected: FAIL
+
+ [:val=".1e-2"]
+ expected: FAIL
+
+ [:val="0x.3"]
+ expected: FAIL
+
+ [:val="0X.3"]
+ expected: FAIL
+
+ [:val="0xa.fp%2B2"]
+ expected: FAIL
+
+ [:val="0xa.fP%2B2"]
+ expected: FAIL
+
+ [:val="0xE.fp%2B2"]
+ expected: FAIL
+
+ [:val="0X1.fp-4"]
+ expected: FAIL
+
+ [:val="1"]
+ expected: FAIL
+
+ [:val="-1"]
+ expected: FAIL
+
+ [:val="1u"]
+ expected: FAIL
+
+ [:val="1i"]
+ expected: FAIL
+
+ [:val=".f"]
+ expected: FAIL
+
+ [:val=".e-2"]
+ expected: FAIL
+
+ [:val="1.e%262f"]
+ expected: FAIL
+
+ [:val="1.ef"]
+ expected: FAIL
+
+ [:val="1.e%2Bf"]
+ expected: FAIL
+
+ [:val="0x.p2"]
+ expected: FAIL
+
+ [:val="0x1p"]
+ expected: FAIL
+
+ [:val="0x1p%5E"]
+ expected: FAIL
+
+ [:val="1.0e%2B999999999999f"]
+ expected: FAIL
+
+ [:val="0x1.0p%2B999999999999f"]
+ expected: FAIL
+
+ [:val="0x1.00000001pf0"]
+ expected: FAIL
+
+ [:val="0h"]
+ expected: FAIL
+
+ [:val="1h"]
+ expected: FAIL
+
+ [:val=".1h"]
+ expected: FAIL
+
+ [:val="1.1e2h"]
+ expected: FAIL
+
+ [:val="1.1E%2B2h"]
+ expected: FAIL
+
+ [:val="2.4e-2h"]
+ expected: FAIL
+
+ [:val="0xep2h"]
+ expected: FAIL
+
+ [:val="0xEp-2h"]
+ expected: FAIL
+
+ [:val="0x3p%2B2h"]
+ expected: FAIL
+
+ [:val="0x3.2p%2B2h"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_func_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:module_scope_multiple:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_fn_var_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:abstract_float:*]
+ [:val="0f"]
+ expected: FAIL
+
+ [:val="0.0f"]
+ expected: FAIL
+
+ [:val="12.223f"]
+ expected: FAIL
+
+ [:val="12.f"]
+ expected: FAIL
+
+ [:val=".12f"]
+ expected: FAIL
+
+ [:val="2.4e%2B4f"]
+ expected: FAIL
+
+ [:val="2.4e-2f"]
+ expected: FAIL
+
+ [:val="2.e%2B4f"]
+ expected: FAIL
+
+ [:val="1e-4f"]
+ expected: FAIL
+
+ [:val="0x1P%2B4f"]
+ expected: FAIL
+
+ [:val="0.0"]
+ expected: FAIL
+
+ [:val=".0"]
+ expected: FAIL
+
+ [:val="12."]
+ expected: FAIL
+
+ [:val="00012."]
+ expected: FAIL
+
+ [:val=".12"]
+ expected: FAIL
+
+ [:val="1.2e2"]
+ expected: FAIL
+
+ [:val="1.2E2"]
+ expected: FAIL
+
+ [:val="1.2e%2B2"]
+ expected: FAIL
+
+ [:val="2.4e-2"]
+ expected: FAIL
+
+ [:val=".1e-2"]
+ expected: FAIL
+
+ [:val="0x.3"]
+ expected: FAIL
+
+ [:val="0X.3"]
+ expected: FAIL
+
+ [:val="0xa.fp%2B2"]
+ expected: FAIL
+
+ [:val="0xa.fP%2B2"]
+ expected: FAIL
+
+ [:val="0xE.fp%2B2"]
+ expected: FAIL
+
+ [:val="0X1.fp-4"]
+ expected: FAIL
+
+ [:val=".f"]
+ expected: FAIL
+
+ [:val=".e-2"]
+ expected: FAIL
+
+ [:val="1.e%262f"]
+ expected: FAIL
+
+ [:val="1.ef"]
+ expected: FAIL
+
+ [:val="1.e%2Bf"]
+ expected: FAIL
+
+ [:val="0x.p2"]
+ expected: FAIL
+
+ [:val="0x1p"]
+ expected: FAIL
+
+ [:val="0x1p%5E"]
+ expected: FAIL
+
+ [:val="1.0e%2B999999999999f"]
+ expected: FAIL
+
+ [:val="0x1.0p%2B999999999999f"]
+ expected: FAIL
+
+ [:val="0x1.00000001pf0"]
+ expected: FAIL
+
+ [:val="0h"]
+ expected: FAIL
+
+ [:val="1h"]
+ expected: FAIL
+
+ [:val=".1h"]
+ expected: FAIL
+
+ [:val="1.1e2h"]
+ expected: FAIL
+
+ [:val="1.1E%2B2h"]
+ expected: FAIL
+
+ [:val="2.4e-2h"]
+ expected: FAIL
+
+ [:val="0xep2h"]
+ expected: FAIL
+
+ [:val="0xEp-2h"]
+ expected: FAIL
+
+ [:val="0x3p%2B2h"]
+ expected: FAIL
+
+ [:val="0x3.2p%2B2h"]
+ expected: FAIL
+
+ [:val="1.1eh"]
+ expected: FAIL
+
+ [:val="1.1e%252h"]
+ expected: FAIL
+
+ [:val="1.1e%2Bh"]
+ expected: FAIL
+
+ [:val="1.0e%2B999999h"]
+ expected: FAIL
+
+ [:val="0x1.0p%2B999999h"]
+ expected: FAIL
+
+ [:val="0xf.h"]
+ expected: FAIL
+
+ [:val="0x3h"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,identifiers:non_normalized:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:i32:*]
+ [:val="0x123"]
+ expected: FAIL
+
+ [:val="123"]
+ expected: FAIL
+
+ [:val="0"]
+ expected: FAIL
+
+ [:val="0x3f"]
+ expected: FAIL
+
+ [:val="2147483647"]
+ expected: FAIL
+
+ [:val="-0x123"]
+ expected: FAIL
+
+ [:val="-123"]
+ expected: FAIL
+
+ [:val="-0x3f"]
+ expected: FAIL
+
+ [:val="-2147483647"]
+ expected: FAIL
+
+ [:val="-2147483648"]
+ expected: FAIL
+
+ [:val="94i"]
+ expected: FAIL
+
+ [:val="2147483647i"]
+ expected: FAIL
+
+ [:val="-2147483647i"]
+ expected: FAIL
+
+ [:val="i32(-2147483648)"]
+ expected: FAIL
+
+ [:val="42u"]
+ expected: FAIL
+
+ [:val="0u"]
+ expected: FAIL
+
+ [:val="4294967295u"]
+ expected: FAIL
+
+ [:val="2147483648"]
+ expected: FAIL
+
+ [:val="2147483648i"]
+ expected: FAIL
+
+ [:val="-2147483649"]
+ expected: FAIL
+
+ [:val="-2147483649i"]
+ expected: FAIL
+
+ [:val="1.0"]
+ expected: FAIL
+
+ [:val="1.0f"]
+ expected: FAIL
+
+ [:val="1.0h"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:bools:*]
+ [:val="true"]
+ expected: FAIL
+
+ [:val="false"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_enable:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:f16:*]
+ [:val="0h"]
+ expected: FAIL
+
+ [:val="1h"]
+ expected: FAIL
+
+ [:val=".1h"]
+ expected: FAIL
+
+ [:val="1.1e2h"]
+ expected: FAIL
+
+ [:val="1.1E%2B2h"]
+ expected: FAIL
+
+ [:val="2.4e-2h"]
+ expected: FAIL
+
+ [:val="0xep2h"]
+ expected: FAIL
+
+ [:val="0xEp-2h"]
+ expected: FAIL
+
+ [:val="0x3p%2B2h"]
+ expected: FAIL
+
+ [:val="0x3.2p%2B2h"]
+ expected: FAIL
+
+ [:val="0.0"]
+ expected: FAIL
+
+ [:val=".0"]
+ expected: FAIL
+
+ [:val="12."]
+ expected: FAIL
+
+ [:val="00012."]
+ expected: FAIL
+
+ [:val=".12"]
+ expected: FAIL
+
+ [:val="1.2e2"]
+ expected: FAIL
+
+ [:val="1.2E2"]
+ expected: FAIL
+
+ [:val="1.2e%2B2"]
+ expected: FAIL
+
+ [:val="2.4e-2"]
+ expected: FAIL
+
+ [:val=".1e-2"]
+ expected: FAIL
+
+ [:val="0x.3"]
+ expected: FAIL
+
+ [:val="0X.3"]
+ expected: FAIL
+
+ [:val="0xa.fp%2B2"]
+ expected: FAIL
+
+ [:val="0xa.fP%2B2"]
+ expected: FAIL
+
+ [:val="0xE.fp%2B2"]
+ expected: FAIL
+
+ [:val="0X1.fp-4"]
+ expected: FAIL
+
+ [:val="1"]
+ expected: FAIL
+
+ [:val="-1"]
+ expected: FAIL
+
+ [:val="0f"]
+ expected: FAIL
+
+ [:val="0.0f"]
+ expected: FAIL
+
+ [:val="12.223f"]
+ expected: FAIL
+
+ [:val="12.f"]
+ expected: FAIL
+
+ [:val=".12f"]
+ expected: FAIL
+
+ [:val="2.4e%2B4f"]
+ expected: FAIL
+
+ [:val="2.4e-2f"]
+ expected: FAIL
+
+ [:val="2.e%2B4f"]
+ expected: FAIL
+
+ [:val="1e-4f"]
+ expected: FAIL
+
+ [:val="0x1P%2B4f"]
+ expected: FAIL
+
+ [:val="1i"]
+ expected: FAIL
+
+ [:val="1u"]
+ expected: FAIL
+
+ [:val="1f"]
+ expected: FAIL
+
+ [:val="1.1eh"]
+ expected: FAIL
+
+ [:val="1.1e%252h"]
+ expected: FAIL
+
+ [:val="1.1e%2Bh"]
+ expected: FAIL
+
+ [:val="1.0e%2B999999h"]
+ expected: FAIL
+
+ [:val="0x1.0p%2B999999h"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_struct_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,literal:abstract_int:*]
+ [:val="0x123"]
+ expected: FAIL
+
+ [:val="123"]
+ expected: FAIL
+
+ [:val="0"]
+ expected: FAIL
+
+ [:val="0x3f"]
+ expected: FAIL
+
+ [:val="2147483647"]
+ expected: FAIL
+
+ [:val="-0x123"]
+ expected: FAIL
+
+ [:val="-123"]
+ expected: FAIL
+
+ [:val="-0x3f"]
+ expected: FAIL
+
+ [:val="-2147483647"]
+ expected: FAIL
+
+ [:val="-2147483648"]
+ expected: FAIL
+
+ [:val="94i"]
+ expected: FAIL
+
+ [:val="2147483647i"]
+ expected: FAIL
+
+ [:val="-2147483647i"]
+ expected: FAIL
+
+ [:val="i32(-2147483648)"]
+ expected: FAIL
+
+ [:val="42u"]
+ expected: FAIL
+
+ [:val="0u"]
+ expected: FAIL
+
+ [:val="4294967295u"]
+ expected: FAIL
+
+ [:val="0123"]
+ expected: FAIL
+
+ [:val="2147483648i"]
+ expected: FAIL
+
+ [:val="-2147483649i"]
+ expected: FAIL
+
+ [:val="4294967295"]
+ expected: FAIL
+
+ [:val="4294967295i"]
+ expected: FAIL
+
+ [:val="4294967296u"]
+ expected: FAIL
+
+ [:val="-1u"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_member:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_call:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_module_const_decl:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:module_scope_single:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,comments:unterminated_block_comment:*]
+ [:terminated=true]
+ expected: FAIL
+
+ [:terminated=false]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/48/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/48/cts.https.html.ini
new file mode 100644
index 0000000000..c98d478acd
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/48/cts.https.html.ini
@@ -0,0 +1,123 @@
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_loop:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_while_continue:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_case_break:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:function_body_single:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_assignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_continuing:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_for:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_if:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_discard:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:compound_statement_single:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_default_case_break:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:function_body_multiple:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_if_else:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_fn_static_assert:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_for_break:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_default_case:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:compound_statement_multiple:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_loop_break:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_while:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_compound_statement:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_case:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_loop_continue:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_loop_break_if:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_switch:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,semicolon:after_while_break:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/49/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/49/cts.https.html.ini
new file mode 100644
index 0000000000..c6387bd091
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/49/cts.https.html.ini
@@ -0,0 +1,9696 @@
+[cts.https.html?q=webgpu:shader,validation,shader_io,invariant:valid_only_with_vertex_position_builtin:*]
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,source:empty:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_return_type:*]
+ [:target_stage=""]
+ expected: FAIL
+
+ [:target_stage="vertex"]
+ expected: FAIL
+
+ [:target_stage="fragment"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,entry_point:no_entry_point_provided:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_param:*]
+ [:target_stage=""]
+ expected: FAIL
+
+ [:target_stage="vertex"]
+ expected: FAIL
+
+ [:target_stage="fragment"]
+ expected: FAIL
+
+ [:target_stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:nesting:*]
+ [:target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:target_stage="";target_io="out"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,source:invalid_source:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_param_struct:*]
+ [:target_stage=""]
+ expected: FAIL
+
+ [:target_stage="vertex"]
+ expected: FAIL
+
+ [:target_stage="fragment"]
+ expected: FAIL
+
+ [:target_stage="compute"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,source:valid_source:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,interpolate:duplicate:*]
+ [:attr=""]
+ expected: FAIL
+
+ [:attr="%40interpolate(flat)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,resource_interface,bindings:binding_attributes:*]
+ [:stage="vertex";has_group=true;has_binding=true]
+ expected: FAIL
+
+ [:stage="vertex";has_group=true;has_binding=false]
+ expected: FAIL
+
+ [:stage="vertex";has_group=false;has_binding=true]
+ expected: FAIL
+
+ [:stage="vertex";has_group=false;has_binding=false]
+ expected: FAIL
+
+ [:stage="fragment";has_group=true;has_binding=true]
+ expected: FAIL
+
+ [:stage="fragment";has_group=true;has_binding=false]
+ expected: FAIL
+
+ [:stage="fragment";has_group=false;has_binding=true]
+ expected: FAIL
+
+ [:stage="fragment";has_group=false;has_binding=false]
+ expected: FAIL
+
+ [:stage="compute";has_group=true;has_binding=true]
+ expected: FAIL
+
+ [:stage="compute";has_group=true;has_binding=false]
+ expected: FAIL
+
+ [:stage="compute";has_group=false;has_binding=true]
+ expected: FAIL
+
+ [:stage="compute";has_group=false;has_binding=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:type:*]
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_type="MyStruct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="bool"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="u32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="i32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="f32"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="array%3Cbool,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="array%3Cu32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="array%3Ci32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="array%3Cf32,4%3E"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_type="MyStruct"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_return_type_struct:*]
+ [:target_stage=""]
+ expected: FAIL
+
+ [:target_stage="vertex"]
+ expected: FAIL
+
+ [:target_stage="fragment"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:reuse_builtin_name:*]
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use="function-var"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use="function-var"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use="function"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use="function"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use="type_name"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use="struct"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use="function"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use="module-var"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use="function-var"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use="type_name"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use="struct"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use="function"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use="module-var"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use="function-var"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use="function-var"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use="type_name"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use="struct"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use="function"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use="module-var"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use="function-var"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use="function-var"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use="function-var"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use="type_name"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use="struct"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use="function"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use="module-var"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use="function-var"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,static_assert:parse:*]
+ [:case="no_parentheses"]
+ expected: FAIL
+
+ [:case="left_parenthesis_only"]
+ expected: FAIL
+
+ [:case="right_parenthesis_only"]
+ expected: FAIL
+
+ [:case="both_parentheses"]
+ expected: FAIL
+
+ [:case="condition_on_newline"]
+ expected: FAIL
+
+ [:case="multiline_with_parentheses"]
+ expected: FAIL
+
+ [:case="invalid_expression"]
+ expected: FAIL
+
+ [:case="no_condition_no_parentheses"]
+ expected: FAIL
+
+ [:case="no_condition_with_parentheses"]
+ expected: FAIL
+
+ [:case="not_a_boolean"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,resource_interface,bindings:different_entry_points:*]
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="vertex";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="fragment";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="vertex";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="fragment";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="storage";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_2d";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="texture_external";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="texture_3d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="texture_storage_1d";usage="transitive"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="direct"]
+ expected: FAIL
+
+ [:a_stage="compute";b_stage="compute";a_kind="uniform";b_kind="uniform";usage="transitive"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,interpolate:integral_types:*]
+ [:stage="vertex";type="i32";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="i32";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="u32";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="vertex";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="i32";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="u32";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec2%3Ci32%3E";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=true;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute=""]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(flat)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(perspective,%20sample)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20center)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20centroid)"]
+ expected: FAIL
+
+ [:stage="fragment";type="vec4%3Cu32%3E";use_struct=false;attribute="%40interpolate(linear,%20sample)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:stage_inout:*]
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,parse,var_and_let:initializer_type:*]
+ [:variableOrConstant="var"]
+ expected: FAIL
+
+ [:variableOrConstant="let"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,invariant:not_valid_on_user_defined_io:*]
+ [:use_invariant=true]
+ expected: FAIL
+
+ [:use_invariant=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,interpolate:require_location:*]
+ [:stage="vertex";attribute="%40location(0)";use_struct=true]
+ expected: FAIL
+
+ [:stage="vertex";attribute="%40location(0)";use_struct=false]
+ expected: FAIL
+
+ [:stage="vertex";attribute="%40builtin(position)";use_struct=true]
+ expected: FAIL
+
+ [:stage="vertex";attribute="%40builtin(position)";use_struct=false]
+ expected: FAIL
+
+ [:stage="fragment";attribute="%40location(0)";use_struct=true]
+ expected: FAIL
+
+ [:stage="fragment";attribute="%40location(0)";use_struct=false]
+ expected: FAIL
+
+ [:stage="fragment";attribute="%40builtin(position)";use_struct=true]
+ expected: FAIL
+
+ [:stage="fragment";attribute="%40builtin(position)";use_struct=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:duplicates:*]
+ [:first="p1";second="p2"]
+ expected: FAIL
+
+ [:first="p1";second="s1b"]
+ expected: FAIL
+
+ [:first="p1";second="s2b"]
+ expected: FAIL
+
+ [:first="p1";second="rb"]
+ expected: FAIL
+
+ [:first="s1a";second="p2"]
+ expected: FAIL
+
+ [:first="s1a";second="s1b"]
+ expected: FAIL
+
+ [:first="s1a";second="s2b"]
+ expected: FAIL
+
+ [:first="s1a";second="rb"]
+ expected: FAIL
+
+ [:first="s2a";second="p2"]
+ expected: FAIL
+
+ [:first="s2a";second="s1b"]
+ expected: FAIL
+
+ [:first="s2a";second="s2b"]
+ expected: FAIL
+
+ [:first="s2a";second="rb"]
+ expected: FAIL
+
+ [:first="ra";second="p2"]
+ expected: FAIL
+
+ [:first="ra";second="s1b"]
+ expected: FAIL
+
+ [:first="ra";second="s2b"]
+ expected: FAIL
+
+ [:first="ra";second="rb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,builtins:missing_vertex_position:*]
+ [:use_struct=true;attribute="%40builtin(position)"]
+ expected: FAIL
+
+ [:use_struct=true;attribute="%40location(0)"]
+ expected: FAIL
+
+ [:use_struct=false;attribute="%40builtin(position)"]
+ expected: FAIL
+
+ [:use_struct=false;attribute="%40location(0)"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,interpolate:type_and_sampling:*]
+ [:stage="vertex";io="in";use_struct=true;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=true;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="in";use_struct=false;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=true;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="vertex";io="out";use_struct=false;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=true;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="in";use_struct=false;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=true;type="sample";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="flat";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="perspective";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="linear";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="center";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="centroid";sampling="linear"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling=""]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="center"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="centroid"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="sample"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="flat"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="perspective"]
+ expected: FAIL
+
+ [:stage="fragment";io="out";use_struct=false;type="sample";sampling="linear"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,resource_interface,bindings:single_entry_point:*]
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="vertex";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="fragment";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="storage";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_2d";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="texture_external";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_3d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="texture_storage_1d";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=0;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=0;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=0;b_binding=3;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=0;usage="transitive"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="direct"]
+ expected: FAIL
+
+ [:stage="compute";a_kind="uniform";b_kind="uniform";a_group=3;b_group=3;a_binding=3;b_binding=3;usage="transitive"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/5/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/5/cts.https.html.ini
new file mode 100644
index 0000000000..5c0c19b7b8
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/5/cts.https.html.ini
@@ -0,0 +1,753 @@
+[cts.https.html?q=webgpu:api,operation,render_pass,clear_value:loaded:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,basic:clear:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,reflection:query_set_reflection_attributes:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,multiple_color_attachments:*]
+ [:storeOperation1="discard";storeOperation2="discard"]
+ expected: FAIL
+
+ [:storeOperation1="discard";storeOperation2="store"]
+ expected: FAIL
+
+ [:storeOperation1="store";storeOperation2="discard"]
+ expected: FAIL
+
+ [:storeOperation1="store";storeOperation2="store"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:*]
+ [:colorFormat="r8unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r8unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r8uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r8uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r8sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r8sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r16uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r16uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r16sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r16sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r16float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r16float";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg8unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg8unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg8uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg8uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg8sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg8sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r32uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r32uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r32sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r32sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="r32float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="r32float";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg16uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg16uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg16sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg16sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg16float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg16float";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba8unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba8unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba8unorm-srgb";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba8unorm-srgb";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba8uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba8uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba8sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba8sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="bgra8unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="bgra8unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="bgra8unorm-srgb";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="bgra8unorm-srgb";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgb10a2unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgb10a2unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg32uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg32uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg32sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg32sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rg32float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rg32float";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba16uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba16uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba16sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba16sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba16float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba16float";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba32uint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba32uint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba32sint";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba32sint";storeOperation="store"]
+ expected: FAIL
+
+ [:colorFormat="rgba32float";storeOperation="discard"]
+ expected: FAIL
+
+ [:colorFormat="rgba32float";storeOperation="store"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_with_depth_stencil_attachment:*]
+ [:colorStoreOperation="discard";depthStencilStoreOperation="discard"]
+ expected: FAIL
+
+ [:colorStoreOperation="discard";depthStencilStoreOperation="store"]
+ expected: FAIL
+
+ [:colorStoreOperation="store";depthStencilStoreOperation="discard"]
+ expected: FAIL
+
+ [:colorStoreOperation="store";depthStencilStoreOperation="store"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,storeop2:storeOp_controls_whether_1x1_drawn_quad_is_stored:*]
+ [:storeOp="store"]
+ expected: FAIL
+
+ [:storeOp="discard"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,sample_mask:final_output:*]
+ [:sampleCount=1;rasterizationMask=0]
+ expected: FAIL
+
+ [:sampleCount=1;rasterizationMask=1]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=0]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=1]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=2]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=3]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=4]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=5]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=6]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=7]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=8]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=9]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=10]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=11]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=12]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=13]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=14]
+ expected: FAIL
+
+ [:sampleCount=4;rasterizationMask=15]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,clear_value:stored:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,clear_value:layout:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,clear_value:srgb:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,primitive_topology:unaligned_vertex_count:*]
+ [:topology="line-list";indirect=false;drawCount=5]
+ expected: FAIL
+
+ [:topology="line-list";indirect=true;drawCount=5]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=false;drawCount=5]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=false;drawCount=4]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=true;drawCount=5]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=true;drawCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,primitive_topology:basic:*]
+ [:topology="point-list";indirect=false;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="point-list";indirect=true;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="line-list";indirect=false;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="line-list";indirect=true;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="line-strip";indirect=false;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="line-strip";indirect=false;primitiveRestart=true]
+ expected: FAIL
+
+ [:topology="line-strip";indirect=true;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="line-strip";indirect=true;primitiveRestart=true]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=false;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="triangle-list";indirect=true;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="triangle-strip";indirect=false;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="triangle-strip";indirect=false;primitiveRestart=true]
+ expected: FAIL
+
+ [:topology="triangle-strip";indirect=true;primitiveRestart=false]
+ expected: FAIL
+
+ [:topology="triangle-strip";indirect=true;primitiveRestart=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,overrides:shared_shader_module:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,overrides:multi_entry_points:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count,blend:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,resolve:render_pass_resolve:*]
+ [:storeOperation="discard"]
+ expected: FAIL
+
+ [:storeOperation="store"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,attachments:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,depth_stencil_attachment_only:*]
+ [:depthStencilFormat="depth32float";storeOperation="discard"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth32float";storeOperation="store"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth16unorm";storeOperation="discard"]
+ expected: FAIL
+
+ [:depthStencilFormat="depth16unorm";storeOperation="store"]
+ expected: FAIL
+
+ [:depthStencilFormat="stencil8";storeOperation="discard"]
+ expected: FAIL
+
+ [:depthStencilFormat="stencil8";storeOperation="store"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,vertex_only_render_pipeline:draw_depth_and_stencil_with_vertex_only_pipeline:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,overrides:basic:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pass,clear_value:stencil_clear_value:*]
+ [:stencilFormat="stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth24plus-stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=0;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=1;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=255;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=258;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=true]
+ expected: FAIL
+
+ [:stencilFormat="depth32float-stencil8";stencilClearValue=65539;applyStencilClearValueAsStencilReferenceValue=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,culling_tests:culling:*]
+ [:frontFace="ccw";cullMode="none"]
+ expected: FAIL
+
+ [:frontFace="ccw";cullMode="front"]
+ expected: FAIL
+
+ [:frontFace="ccw";cullMode="back"]
+ expected: FAIL
+
+ [:frontFace="cw";cullMode="none"]
+ expected: FAIL
+
+ [:frontFace="cw";cullMode="front"]
+ expected: FAIL
+
+ [:frontFace="cw";cullMode="back"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,render_pipeline,overrides:precision:*]
+ [:isAsync=true]
+ expected: FAIL
+
+ [:isAsync=false]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/50/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/50/cts.https.html.ini
new file mode 100644
index 0000000000..3f95fbbdf3
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/50/cts.https.html.ini
@@ -0,0 +1,1945 @@
+[cts.https.html?q=webgpu:shader,validation,shader_io,locations:type:*]
+ [:use_struct=true;type="f32"]
+ expected: FAIL
+
+ [:use_struct=true;type="i32"]
+ expected: FAIL
+
+ [:use_struct=true;type="u32"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2f"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2i"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2u"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3f"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3i"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3u"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4f"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4i"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4u"]
+ expected: FAIL
+
+ [:use_struct=true;type="MyAlias"]
+ expected: FAIL
+
+ [:use_struct=true;type="bool"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x2f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x3f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat2x4f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x2f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x3f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat3x4f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x2f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x3f"]
+ expected: FAIL
+
+ [:use_struct=true;type="mat4x4f"]
+ expected: FAIL
+
+ [:use_struct=true;type="array%3Cf32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="array%3Ci32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="array%3Cu32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="array%3Cbool,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="MyStruct"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_1d%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_2d%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_2d_array%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_3d%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_cube%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_cube_array%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_multisampled_2d%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_external"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_storage_1d%3Crgba8unorm,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_storage_2d%3Crg32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_storage_2d_array%3Cr32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_storage_3d%3Cr32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_depth_2d"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_depth_cube"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_depth_cube_array"]
+ expected: FAIL
+
+ [:use_struct=true;type="texture_depth_multisampled_2d"]
+ expected: FAIL
+
+ [:use_struct=true;type="sampler"]
+ expected: FAIL
+
+ [:use_struct=true;type="sampler_comparison"]
+ expected: FAIL
+
+ [:use_struct=false;type="f32"]
+ expected: FAIL
+
+ [:use_struct=false;type="i32"]
+ expected: FAIL
+
+ [:use_struct=false;type="u32"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="vec2f"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2i"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2u"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="vec3f"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3i"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3u"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="vec4f"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4i"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4u"]
+ expected: FAIL
+
+ [:use_struct=false;type="MyAlias"]
+ expected: FAIL
+
+ [:use_struct=false;type="bool"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec2%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec3%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="vec4%3Cbool%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x2%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x3%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x4%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x2f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x3f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x4f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x2f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x3f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat3x4f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x2f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x3f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat4x4f"]
+ expected: FAIL
+
+ [:use_struct=false;type="mat2x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat2x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat2x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat3x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat3x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat3x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat4x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat4x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="mat4x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="array%3Cf32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="array%3Ci32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="array%3Cu32,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="array%3Cbool,%2012%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="atomic%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="atomic%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="MyStruct"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_1d%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_2d%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_2d_array%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_3d%3Cf32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_cube%3Cu32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_cube_array%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_multisampled_2d%3Ci32%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_external"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_storage_1d%3Crgba8unorm,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_storage_2d%3Crg32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_storage_2d_array%3Cr32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_storage_3d%3Cr32float,%20write%3E"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_depth_2d"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_depth_2d_array"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_depth_cube"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_depth_cube_array"]
+ expected: FAIL
+
+ [:use_struct=false;type="texture_depth_multisampled_2d"]
+ expected: FAIL
+
+ [:use_struct=false;type="sampler"]
+ expected: FAIL
+
+ [:use_struct=false;type="sampler_comparison"]
+ expected: FAIL
+
+ [:use_struct=true;type="f16"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="vec2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="vec3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="vec4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat2x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat2x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat2x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat3x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat3x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat3x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat4x2h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat4x3h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=true;type="mat4x4h"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:use_struct=false;type="f16"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:usage:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:alpha_mode:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:snorm_texel_data_in_shader:*]
+ [:format="r8snorm"]
+ expected: FAIL
+
+ [:format="rg8snorm"]
+ expected: FAIL
+
+ [:format="rgba8snorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:size_zero_before_configure:*]
+ [:canvasType="onscreen";zeroDimension="width"]
+ expected: FAIL
+
+ [:canvasType="onscreen";zeroDimension="height"]
+ expected: FAIL
+
+ [:canvasType="offscreen";zeroDimension="width"]
+ expected: FAIL
+
+ [:canvasType="offscreen";zeroDimension="height"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,static_assert,static_assert:constant_expression:*]
+ [:case="true_literal";scope="module"]
+ expected: FAIL
+
+ [:case="true_literal";scope="function"]
+ expected: FAIL
+
+ [:case="not_false";scope="module"]
+ expected: FAIL
+
+ [:case="not_false";scope="function"]
+ expected: FAIL
+
+ [:case="const_eq_literal_int";scope="module"]
+ expected: FAIL
+
+ [:case="const_eq_literal_int";scope="function"]
+ expected: FAIL
+
+ [:case="const_eq_literal_float";scope="module"]
+ expected: FAIL
+
+ [:case="const_eq_literal_float";scope="function"]
+ expected: FAIL
+
+ [:case="binary_op_eq_const";scope="module"]
+ expected: FAIL
+
+ [:case="binary_op_eq_const";scope="function"]
+ expected: FAIL
+
+ [:case="any";scope="module"]
+ expected: FAIL
+
+ [:case="any";scope="function"]
+ expected: FAIL
+
+ [:case="min_max";scope="module"]
+ expected: FAIL
+
+ [:case="min_max";scope="function"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:unorm_texel_data_in_shader:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:viewFormats:*]
+ [:canvasType="onscreen";format="bgra8unorm";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba16float";viewFormatFeature="_undef_"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba16float";viewFormatFeature="texture-compression-bc"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float";viewFormatFeature="depth32float-stencil8"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float";viewFormatFeature="texture-compression-etc2"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float";viewFormatFeature="texture-compression-astc"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm";viewFormatFeature="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm";viewFormatFeature="texture-compression-etc2"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm";viewFormatFeature="texture-compression-astc"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm";viewFormatFeature="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm";viewFormatFeature="texture-compression-etc2"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm";viewFormatFeature="texture-compression-astc"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba16float";viewFormatFeature="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba16float";viewFormatFeature="texture-compression-etc2"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="rgba16float";viewFormatFeature="texture-compression-astc"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:format:*]
+ [:canvasType="onscreen";format="r8unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r8snorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r8uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r8sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r16uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r16sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r16float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg8unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg8snorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg8uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg8sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r32uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r32sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="r32float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg16uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg16sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg16float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8snorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba8sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg32uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg32sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rg32float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba16float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba32uint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba32sint"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="rgba32float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="depth32float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="depth16unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="stencil8"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="depth24plus"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="onscreen";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r8unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r8snorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r8uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r8sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r16uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r16sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r16float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg8unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg8snorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg8uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg8sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r32uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r32sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="r32float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg16uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg16sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg16float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8snorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba8sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg32uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg32sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rg32float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba16uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba16sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba16float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba32uint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba32sint"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="rgba32float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="depth32float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="depth16unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="stencil8"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="depth24plus"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="bc1-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc1-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc2-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc2-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc3-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc3-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc4-r-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc4-r-snorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc5-rg-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc5-rg-snorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc6h-rgb-ufloat"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc6h-rgb-float"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc7-rgba-unorm"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="bc7-rgba-unorm-srgb"]
+ expected: FAIL
+
+ [:canvasType="offscreen";format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="offscreen";format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="depth32float-stencil8"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgb8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgb8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgb8a1unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgb8a1unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgba8unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="etc2-rgba8unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="eac-r11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="eac-r11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="eac-rg11unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="eac-rg11snorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-4x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-4x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-5x4-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-5x4-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-5x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-5x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-6x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-6x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-6x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-6x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-8x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x5-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x5-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x6-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x6-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x8-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x8-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-10x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-12x10-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-12x10-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-12x12-unorm"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+ [:canvasType="onscreen";format="astc-12x12-unorm-srgb"]
+ expected:
+ if os == "mac": PASS
+ FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texture_ok:norm:*]
+ [:mode="bytes";format="r8unorm"]
+ expected: FAIL
+
+ [:mode="bytes";format="r8snorm"]
+ expected: FAIL
+
+ [:mode="colors";format="r8unorm"]
+ expected: FAIL
+
+ [:mode="colors";format="r8snorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texture_ok:float32:*]
+ [:format="rgba32float"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,invariant:duplicate:*]
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="vertex_index";stage="vertex";io="in";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="instance_index";stage="vertex";io="in";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="position";stage="vertex";io="out";type="vec4%3Cf32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="position";stage="fragment";io="in";type="vec4%3Cf32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="front_facing";stage="fragment";io="in";type="bool";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="frag_depth";stage="fragment";io="out";type="f32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="local_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="local_invocation_index";stage="compute";io="in";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="global_invocation_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="workgroup_id";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="num_workgroups";stage="compute";io="in";type="vec3%3Cu32%3E";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="sample_index";stage="fragment";io="in";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="in";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;attr=""]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=true;attr="%40invariant"]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;attr=""]
+ expected: FAIL
+
+ [:name="sample_mask";stage="fragment";io="out";type="u32";use_struct=false;attr="%40invariant"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,locations:stage_inout:*]
+ [:use_struct=true;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=true;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:use_struct=true;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=true;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:use_struct=true;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=true;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="compute";target_io="in"]
+ expected: FAIL
+
+ [:use_struct=false;target_stage="compute";target_io="out"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,static_assert,static_assert:evaluation_stage:*]
+ [:scope="module";stage="constant"]
+ expected: FAIL
+
+ [:scope="module";stage="override"]
+ expected: FAIL
+
+ [:scope="module";stage="runtime"]
+ expected: FAIL
+
+ [:scope="function";stage="constant"]
+ expected: FAIL
+
+ [:scope="function";stage="override"]
+ expected: FAIL
+
+ [:scope="function";stage="runtime"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,locations:duplicates:*]
+ [:first="p1";second="p2"]
+ expected: FAIL
+
+ [:first="p1";second="s1b"]
+ expected: FAIL
+
+ [:first="p1";second="s2b"]
+ expected: FAIL
+
+ [:first="p1";second="rb"]
+ expected: FAIL
+
+ [:first="s1a";second="p2"]
+ expected: FAIL
+
+ [:first="s1a";second="s1b"]
+ expected: FAIL
+
+ [:first="s1a";second="s2b"]
+ expected: FAIL
+
+ [:first="s1a";second="rb"]
+ expected: FAIL
+
+ [:first="s2a";second="p2"]
+ expected: FAIL
+
+ [:first="s2a";second="s1b"]
+ expected: FAIL
+
+ [:first="s2a";second="s2b"]
+ expected: FAIL
+
+ [:first="s2a";second="rb"]
+ expected: FAIL
+
+ [:first="ra";second="p2"]
+ expected: FAIL
+
+ [:first="ra";second="s1b"]
+ expected: FAIL
+
+ [:first="ra";second="s2b"]
+ expected: FAIL
+
+ [:first="ra";second="rb"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,locations:nesting:*]
+ [:target_stage="vertex";target_io="in"]
+ expected: FAIL
+
+ [:target_stage="vertex";target_io="out"]
+ expected: FAIL
+
+ [:target_stage="fragment";target_io="in"]
+ expected: FAIL
+
+ [:target_stage="fragment";target_io="out"]
+ expected: FAIL
+
+ [:target_stage="";target_io="in"]
+ expected: FAIL
+
+ [:target_stage="";target_io="out"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:sint_texel_data_in_shader:*]
+ [:format="r8sint"]
+ expected: FAIL
+
+ [:format="r16sint"]
+ expected: FAIL
+
+ [:format="rg8sint"]
+ expected: FAIL
+
+ [:format="r32sint"]
+ expected: FAIL
+
+ [:format="rg16sint"]
+ expected: FAIL
+
+ [:format="rgba8sint"]
+ expected: FAIL
+
+ [:format="rg32sint"]
+ expected: FAIL
+
+ [:format="rgba16sint"]
+ expected: FAIL
+
+ [:format="rgba32sint"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:size_zero_after_configure:*]
+ [:canvasType="onscreen";zeroDimension="width"]
+ expected: FAIL
+
+ [:canvasType="onscreen";zeroDimension="height"]
+ expected: FAIL
+
+ [:canvasType="offscreen";zeroDimension="width"]
+ expected: FAIL
+
+ [:canvasType="offscreen";zeroDimension="height"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:ufloat_texel_data_in_shader:*]
+ [:format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:format="rgb9e5ufloat"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:uint_texel_data_in_shader:*]
+ [:format="r8uint"]
+ expected: FAIL
+
+ [:format="r16uint"]
+ expected: FAIL
+
+ [:format="rg8uint"]
+ expected: FAIL
+
+ [:format="r32uint"]
+ expected: FAIL
+
+ [:format="rg16uint"]
+ expected: FAIL
+
+ [:format="rgba8uint"]
+ expected: FAIL
+
+ [:format="rg32uint"]
+ expected: FAIL
+
+ [:format="rgba16uint"]
+ expected: FAIL
+
+ [:format="rgba32uint"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:device:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,configure:defaults:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texture_ok:snorm_min:*]
+ [:mode="bytes";format="r8snorm"]
+ expected: FAIL
+
+ [:mode="colors";format="r8snorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:util,texture,texel_data:float_texel_data_in_shader:*]
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="r32float"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rg32float"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+ [:format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:shader,validation,shader_io,invariant:invalid_use_of_parameters:*]
+ [:suffix=""]
+ expected: FAIL
+
+ [:suffix="()"]
+ expected: FAIL
+
+ [:suffix="(0)"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/51/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/51/cts.https.html.ini
new file mode 100644
index 0000000000..d3e8348b6d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/51/cts.https.html.ini
@@ -0,0 +1,4102 @@
+[cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:*]
+ [:canvasType="onscreen";dstColorFormat="r8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="r32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rg32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";dstColorFormat="rgba32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="r32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rg32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="bgra8unorm-srgb";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgb10a2unorm";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba16float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba16float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba32float";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";dstColorFormat="rgba32float";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,external_texture,video:importExternalTexture,sample:*]
+ [:sourceType="VideoElement";videoName="red-green.webmvp8.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.theora.ogv"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.mp4"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt601.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt709.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt2020.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.webmvp8.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.theora.ogv"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.mp4"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt601.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt709.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt2020.vp9.webm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,worker,worker:worker:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:offscreenCanvas,snapshot:*]
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="convertToBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="transferToImageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:drawTo2DCanvas:*]
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="onscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="onscreen"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";webgpuCanvasType="offscreen";canvas2DType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:*]
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,getCurrentTexture:resize:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,getCurrentTexture:single_frames:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,external_texture,video:importExternalTexture,expired:*]
+ [:sourceType="VideoElement"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,snapshot:*]
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="srgb";snapshotType="imageBitmap"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toDataURL"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="toBlob"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";colorSpace="display-p3";snapshotType="imageBitmap"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,getCurrentTexture:configured:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:copy_subrect_from_ImageData:*]
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,context_creation:return_type:*]
+ [:offscreen=false]
+ expected:
+ if os == "win": FAIL
+ # This intermittently fails on Linux shippable.
+ # See <https://bugzilla.mozilla.org/show_bug.cgi?id=1824038>.
+ if os == "linux": [PASS, FAIL]
+ PASS
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:transferToImageBitmap_unconfigured_nonzero_size:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:*]
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="r32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rg32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="bgra8unorm-srgb";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgb10a2unorm";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba16float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=true;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba32float";srcPremultiplied=false;dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:*]
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="opaque";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";srcAlphaMode="premultiplied";dstAlphaMode="premultiplied";srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:color_space_conversion:*]
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="srgb";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="r32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rg32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgb10a2unorm";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba16float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=true;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=true;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=false;srcDoFlipYDuringCopy=true]
+ expected: FAIL
+
+ [:srcColorSpace="display-p3";dstColorSpace="srgb";dstColorFormat="rgba32float";dstPremultiplied=false;srcDoFlipYDuringCopy=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,uploadToWebGL:*]
+ [:format="bgra8unorm";alphaMode="opaque";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="opaque";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="bgra8unorm";alphaMode="premultiplied";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="opaque";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba8unorm";alphaMode="premultiplied";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="opaque";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";webgl="webgl";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";webgl="webgl";upload="texSubImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";webgl="webgl2";upload="texImage2D"]
+ expected: FAIL
+
+ [:format="rgba16float";alphaMode="premultiplied";webgl="webgl2";upload="texSubImage2D"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:*]
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";dstPremultiplied=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,external_texture,video:importExternalTexture,compute:*]
+ [:sourceType="VideoElement";videoName="red-green.webmvp8.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.theora.ogv"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.mp4"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt601.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt709.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoElement";videoName="red-green.bt2020.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.webmvp8.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.theora.ogv"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.mp4"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt601.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt709.vp9.webm"]
+ expected: FAIL
+
+ [:sourceType="VideoFrame";videoName="red-green.bt2020.vp9.webm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:transferToImageBitmap_zero_size:*]
+ [:configure=true]
+ expected: FAIL
+
+ [:configure=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:copy_subrect_from_2D_Canvas:*]
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="none";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=true;dstPremultiplied=false]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=true]
+ expected: FAIL
+
+ [:orientation="flipY";srcDoFlipYDuringCopy=false;dstPremultiplied=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:web_platform,canvas,getCurrentTexture:multiple_frames:*]
+ [:canvasType="onscreen"]
+ expected: FAIL
+
+ [:canvasType="offscreen"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/6/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/6/cts.https.html.ini
new file mode 100644
index 0000000000..ca7e5c8c75
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/6/cts.https.html.ini
@@ -0,0 +1,6297 @@
+[cts.https.html?q=webgpu:api,operation,rendering,depth:reverse_depth:*]
+ [:reversed=false]
+ expected: FAIL
+
+ [:reversed=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,draw:default_arguments:*]
+ [:mode="draw"]
+ expected: FAIL
+
+ [:mode="drawIndexed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth_bias:depth_bias:*]
+ [:quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0]
+ expected: FAIL
+
+ [:quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0.125]
+ expected: FAIL
+
+ [:quadAngle=0;bias=-8388608;biasSlopeScale=0;biasClamp=0.125]
+ expected: FAIL
+
+ [:quadAngle=0;bias=-8388608;biasSlopeScale=0;biasClamp=-0.125]
+ expected: FAIL
+
+ [:quadAngle=1;bias=0;biasSlopeScale=0;biasClamp=0]
+ expected: FAIL
+
+ [:quadAngle=1;bias=0;biasSlopeScale=1;biasClamp=0]
+ expected: FAIL
+
+ [:quadAngle=1;bias=0;biasSlopeScale=-0.5;biasClamp=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,basic:fullscreen_quad:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_clamp_and_clip:*]
+ [:format="depth32float";unclippedDepth="_undef_";writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth="_undef_";writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth="_undef_";writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth="_undef_";writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=false;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=false;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=false;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=false;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth="_undef_";writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth="_undef_";writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth="_undef_";writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth="_undef_";writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth="_undef_";writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth="_undef_";writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth="_undef_";writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth="_undef_";writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth="_undef_";writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth="_undef_";writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth="_undef_";writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth="_undef_";writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth="_undef_";writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth="_undef_";writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth="_undef_";writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth="_undef_";writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;writeDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;writeDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;writeDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;writeDepth=true;multisampled=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth_bias:depth_bias_24bit_format:*]
+ [:format="depth24plus";quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0]
+ expected: FAIL
+
+ [:format="depth24plus";quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0.1]
+ expected: FAIL
+
+ [:format="depth24plus";quadAngle=1;bias=8388608;biasSlopeScale=1;biasClamp=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";quadAngle=0;bias=8388608;biasSlopeScale=0;biasClamp=0.1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";quadAngle=1;bias=8388608;biasSlopeScale=1;biasClamp=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,draw:vertex_attributes,basic:*]
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=1;vertex_buffer_count=1;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=1;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="uint32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=4;vertex_buffer_count=4;vertex_format="float32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=1;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="uint32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=4;vertex_format="float32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="uint32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=8;vertex_buffer_count=8;vertex_format="float32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=1;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="uint32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=4;vertex_format="float32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="uint32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="uint32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="uint32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="uint32";step_mode="mixed"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="float32";step_mode="_undef_"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="float32";step_mode="vertex"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="float32";step_mode="instance"]
+ expected: FAIL
+
+ [:vertex_attribute_count=16;vertex_buffer_count=8;vertex_format="float32";step_mode="mixed"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,indirect_draw:basics:*]
+ [:isIndexed=true]
+ expected: FAIL
+
+ [:isIndexed=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blend_constant,setting:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blend_constant,initial:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth:depth_write_disabled:*]
+ [:depthWriteEnabled=false;lastDepth=0]
+ expected: FAIL
+
+ [:depthWriteEnabled=false;lastDepth=1]
+ expected: FAIL
+
+ [:depthWriteEnabled=true;lastDepth=0]
+ expected: FAIL
+
+ [:depthWriteEnabled=true;lastDepth=1]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:*]
+ [:format="depth32float";unclippedDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float";unclippedDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth16unorm";unclippedDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus";unclippedDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";unclippedDepth=true;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=false;multisampled=true]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;multisampled=false]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";unclippedDepth=true;multisampled=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth:depth_test_fail:*]
+ [:secondDepth=1;lastDepth=2]
+ expected: FAIL
+
+ [:secondDepth=0;lastDepth=2]
+ expected: FAIL
+
+ [:secondDepth=2;lastDepth=0.9]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth:depth_disabled:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blend_constant,not_inherited:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blending,formats:*]
+ [:format="r8unorm"]
+ expected: FAIL
+
+ [:format="r16float"]
+ expected: FAIL
+
+ [:format="rg8unorm"]
+ expected: FAIL
+
+ [:format="rg16float"]
+ expected: FAIL
+
+ [:format="rgba8unorm"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="bgra8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:format="rgba16float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blending,GPUBlendComponent:*]
+ [:component="color";srcFactor="zero";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="zero";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one";operation="min"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one";operation="max"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="constant";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="color";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="zero";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one";operation="min"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one";operation="max"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-src-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="dst-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-dst-alpha";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="src-alpha-saturated";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="constant";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="zero";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="zero";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="zero";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-src-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-dst-alpha";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="src-alpha-saturated";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="constant";operation="reverse-subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="add"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="subtract"]
+ expected: FAIL
+
+ [:component="alpha";srcFactor="one-minus-constant";dstFactor="one-minus-constant";operation="reverse-subtract"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,draw:largeish_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:color_write_mask,blending_disabled:*]
+ [:disabled=false]
+ expected: FAIL
+
+ [:disabled=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,depth:depth_compare_func:*]
+ [:format="depth32float";depthCompare="never";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="never";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="never";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="less-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="not-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="not-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="not-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="greater";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="always";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="always";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float";depthCompare="always";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="never";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="never";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="never";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="less-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="not-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="not-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="not-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="greater";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="always";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="always";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth16unorm";depthCompare="always";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="never";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="never";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="never";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="less-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="not-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="not-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="not-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="greater";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="always";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="always";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus";depthCompare="always";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="never";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="never";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="never";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="less-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="not-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="not-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="not-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="greater";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="always";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="always";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthCompare="always";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="never";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="never";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="never";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="less-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="not-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="not-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="not-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater-equal";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater-equal";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater-equal";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="greater";depthClearValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="always";depthClearValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="always";depthClearValue=0.5001]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthCompare="always";depthClearValue=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:blending,clamping:*]
+ [:format="rgba8unorm";srcValue=0.4;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=0.4;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=0.6;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=0.6;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=0.8;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=0.8;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=1;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rgba8unorm";srcValue=1;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.4;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.4;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.6;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.6;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.8;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=0.8;dstValue=0.4]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=1;dstValue=0.2]
+ expected: FAIL
+
+ [:format="rg16float";srcValue=1;dstValue=0.4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,color_target_state:color_write_mask,channel_work:*]
+ [:mask=0]
+ expected: FAIL
+
+ [:mask=1]
+ expected: FAIL
+
+ [:mask=2]
+ expected: FAIL
+
+ [:mask=3]
+ expected: FAIL
+
+ [:mask=4]
+ expected: FAIL
+
+ [:mask=5]
+ expected: FAIL
+
+ [:mask=6]
+ expected: FAIL
+
+ [:mask=7]
+ expected: FAIL
+
+ [:mask=8]
+ expected: FAIL
+
+ [:mask=9]
+ expected: FAIL
+
+ [:mask=10]
+ expected: FAIL
+
+ [:mask=11]
+ expected: FAIL
+
+ [:mask=12]
+ expected: FAIL
+
+ [:mask=13]
+ expected: FAIL
+
+ [:mask=14]
+ expected: FAIL
+
+ [:mask=15]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,basic:large_draw:*]
+ [:indexed=true;indirect=true]
+ expected: FAIL
+
+ [:indexed=true;indirect=false]
+ expected: FAIL
+
+ [:indexed=false;indirect=true]
+ expected: FAIL
+
+ [:indexed=false;indirect=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,draw:vertex_attributes,formats:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:*]
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=0;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=0;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=3;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=0;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=0;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=1;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=false;indirect=false;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=0;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=false;indirect=true;vertex_buffer_offset=32;index_buffer_offset="_undef_";base_vertex="_undef_"]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=false;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=0;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=0;base_vertex=9]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=0]
+ expected: FAIL
+
+ [:first=3;count=6;first_instance=2;instance_count=4;indexed=true;indirect=true;vertex_buffer_offset=32;index_buffer_offset=16;base_vertex=9]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/7/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/7/cts.https.html.ini
new file mode 100644
index 0000000000..aa9e4b30ca
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/7/cts.https.html.ini
@@ -0,0 +1,1710 @@
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:resolve_query_set_to_partial_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_draw_indirect:*]
+ [:test_indexed_draw=true]
+ expected: FAIL
+
+ [:test_indexed_draw=false]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_partial_buffer:*]
+ [:bufferUsage=9]
+ expected: FAIL
+
+ [:bufferUsage=6]
+ expected: FAIL
+
+ [:bufferUsage=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:index_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_reference_initialized:*]
+ [:format="stencil8"]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:format="depth32float-stencil8"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:partial_write_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:storage_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_texture:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:uniform_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:readonly_storage_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_mipmap_color:*]
+ [:maxAnisotropy=1]
+ expected: FAIL
+
+ [:maxAnisotropy=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_passOp_operation:*]
+ [:format="stencil8";passOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="stencil8";passOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="stencil8";passOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="stencil8";passOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="stencil8";passOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";passOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";passOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";passOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_buffer_copy_source:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:map_whole_buffer:*]
+ [:mapMode=1]
+ expected: FAIL
+
+ [:mapMode=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_failOp_operation:*]
+ [:format="stencil8";failOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="stencil8";failOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="stencil8";failOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="stencil8";failOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="stencil8";failOp="decrement-wrap";initialStencil=2]
+ expected: FAIL
+
+ [:format="stencil8";failOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="stencil8";failOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="decrement-wrap";initialStencil=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";failOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="decrement-wrap";initialStencil=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";failOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_compare_func:*]
+ [:format="stencil8";stencilCompare="always";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="always";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="always";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="greater-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="less-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="never";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="never";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="never";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="not-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="not-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";stencilCompare="not-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="always";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="always";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="always";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="greater-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="less-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="never";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="never";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="never";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="not-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="not-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";stencilCompare="not-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="always";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="always";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="always";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="greater-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="less-equal";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="never";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="never";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="never";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="not-equal";stencilRefValue=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="not-equal";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";stencilCompare="not-equal";stencilRefValue=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:map_partial_buffer:*]
+ [:mapMode=1]
+ expected: FAIL
+
+ [:mapMode=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_read_write_mask:*]
+ [:format="stencil8";maskType="write";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";maskType="write";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="stencil8";maskType="read";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="stencil8";maskType="read";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";maskType="write";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";maskType="write";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";maskType="read";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";maskType="read";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";maskType="write";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";maskType="write";stencilRefValue=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";maskType="read";stencilRefValue=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";maskType="read";stencilRefValue=2]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_whole_buffer:*]
+ [:bufferUsage=9]
+ expected: FAIL
+
+ [:bufferUsage=6]
+ expected: FAIL
+
+ [:bufferUsage=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_checkerboard:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:vertex_buffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:*]
+ [:dimension="1d";readMethod="CopyToBuffer";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToBuffer";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="CopyToTexture";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="r32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="1d";readMethod="Sample";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToBuffer";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="CopyToTexture";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="r32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="Sample";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="DepthTest";format="depth32float"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="DepthTest";format="depth16unorm"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="DepthTest";format="depth24plus"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="DepthTest";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="DepthTest";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="StencilTest";format="stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="StencilTest";format="depth24plus-stencil8"]
+ expected: FAIL
+
+ [:dimension="2d";readMethod="StencilTest";format="depth32float-stencil8"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToBuffer";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="CopyToTexture";format="rgba32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="r32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba8snorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba8uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba8sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="bgra8unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgb10a2unorm"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg11b10ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgb9e5ufloat"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rg32float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba16uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba16sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba16float"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba32uint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba32sint"]
+ expected: FAIL
+
+ [:dimension="3d";readMethod="Sample";format="rgba32float"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,rendering,stencil:stencil_depthFailOp_operation:*]
+ [:format="depth24plus-stencil8";depthFailOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="decrement-wrap";initialStencil=2]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth24plus-stencil8";depthFailOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="keep";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="zero";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="replace";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="invert";initialStencil=240]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="increment-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="increment-clamp";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="increment-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="increment-wrap";initialStencil=255]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="decrement-clamp";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="decrement-clamp";initialStencil=0]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="decrement-wrap";initialStencil=2]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="decrement-wrap";initialStencil=1]
+ expected: FAIL
+
+ [:format="depth32float-stencil8";depthFailOp="decrement-wrap";initialStencil=0]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_dispatch_indirect:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,resource_init,buffer:copy_texture_to_partial_buffer:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/8/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/8/cts.https.html.ini
new file mode 100644
index 0000000000..8e3ff2d267
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/8/cts.https.html.ini
@@ -0,0 +1,1137 @@
+[cts.https.html?q=webgpu:api,operation,texture_view,read:aspect:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,write:aspect:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,format_reinterpretation:render_and_resolve_attachment:*]
+ [:format="rgba8unorm";viewFormat="rgba8unorm-srgb";sampleCount=1]
+ expected: FAIL
+
+ [:format="rgba8unorm";viewFormat="rgba8unorm-srgb";sampleCount=4]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";viewFormat="rgba8unorm";sampleCount=1]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";viewFormat="rgba8unorm";sampleCount=4]
+ expected: FAIL
+
+ [:format="bgra8unorm";viewFormat="bgra8unorm-srgb";sampleCount=1]
+ expected: FAIL
+
+ [:format="bgra8unorm";viewFormat="bgra8unorm-srgb";sampleCount=4]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";viewFormat="bgra8unorm";sampleCount=1]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";viewFormat="bgra8unorm";sampleCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:*]
+ [:format="uint8x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint8x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint8x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint8x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint8x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint8x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint8x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint8x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint8x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint8x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint8x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint8x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint8x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint8x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint8x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint8x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="unorm8x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="unorm8x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="unorm8x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="unorm8x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="unorm8x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="unorm8x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="unorm8x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="unorm8x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="snorm8x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="snorm8x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="snorm8x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="snorm8x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="snorm8x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="snorm8x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="snorm8x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="snorm8x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint16x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint16x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint16x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint16x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint16x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint16x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint16x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint16x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint16x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint16x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint16x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint16x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint16x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint16x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint16x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint16x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="unorm16x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="unorm16x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="unorm16x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="unorm16x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="unorm16x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="unorm16x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="unorm16x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="unorm16x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="snorm16x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="snorm16x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="snorm16x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="snorm16x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="snorm16x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="snorm16x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="snorm16x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="snorm16x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float16x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float16x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float16x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float16x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float16x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float16x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float16x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float16x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float32";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float32";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float32";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float32";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float32x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float32x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float32x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float32x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float32x3";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float32x3";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float32x3";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float32x3";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="float32x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="float32x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="float32x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="float32x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint32";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint32";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint32";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint32";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint32x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint32x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint32x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint32x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint32x3";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint32x3";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint32x3";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint32x3";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="uint32x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="uint32x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="uint32x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="uint32x4";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint32";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint32";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint32";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint32";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint32x2";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint32x2";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint32x2";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint32x2";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint32x3";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint32x3";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint32x3";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint32x3";shaderComponentCount=4]
+ expected: FAIL
+
+ [:format="sint32x4";shaderComponentCount=1]
+ expected: FAIL
+
+ [:format="sint32x4";shaderComponentCount=2]
+ expected: FAIL
+
+ [:format="sint32x4";shaderComponentCount=3]
+ expected: FAIL
+
+ [:format="sint32x4";shaderComponentCount=4]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,format_reinterpretation:texture_binding:*]
+ [:format="rgba8unorm";viewFormat="rgba8unorm-srgb"]
+ expected: FAIL
+
+ [:format="rgba8unorm-srgb";viewFormat="rgba8unorm"]
+ expected: FAIL
+
+ [:format="bgra8unorm";viewFormat="bgra8unorm-srgb"]
+ expected: FAIL
+
+ [:format="bgra8unorm-srgb";viewFormat="bgra8unorm"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,uncapturederror:constructor:*]
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,uncapturederror:uncapturederror_from_non_originating_thread:*]
+
+[cts.https.html?q=webgpu:api,operation,texture_view,read:format:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,write:format:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:buffers_with_varying_step_mode:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,write:dimension:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,shader_module,compilation_info:offset_and_length:*]
+ [:valid=true;name="ascii"]
+ expected: FAIL
+
+ [:valid=true;name="unicode"]
+ expected: FAIL
+
+ [:valid=false;name="ascii"]
+ expected: FAIL
+
+ [:valid=false;name="unicode"]
+ expected: FAIL
+
+ [:valid=false;name="carriage-return"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:*]
+ [:format="uint8x2"]
+ expected: FAIL
+
+ [:format="uint8x4"]
+ expected: FAIL
+
+ [:format="sint8x2"]
+ expected: FAIL
+
+ [:format="sint8x4"]
+ expected: FAIL
+
+ [:format="unorm8x2"]
+ expected: FAIL
+
+ [:format="unorm8x4"]
+ expected: FAIL
+
+ [:format="snorm8x2"]
+ expected: FAIL
+
+ [:format="snorm8x4"]
+ expected: FAIL
+
+ [:format="uint16x2"]
+ expected: FAIL
+
+ [:format="uint16x4"]
+ expected: FAIL
+
+ [:format="sint16x2"]
+ expected: FAIL
+
+ [:format="sint16x4"]
+ expected: FAIL
+
+ [:format="unorm16x2"]
+ expected: FAIL
+
+ [:format="unorm16x4"]
+ expected: FAIL
+
+ [:format="snorm16x2"]
+ expected: FAIL
+
+ [:format="snorm16x4"]
+ expected: FAIL
+
+ [:format="float16x2"]
+ expected: FAIL
+
+ [:format="float16x4"]
+ expected: FAIL
+
+ [:format="float32"]
+ expected: FAIL
+
+ [:format="float32x2"]
+ expected: FAIL
+
+ [:format="float32x3"]
+ expected: FAIL
+
+ [:format="float32x4"]
+ expected: FAIL
+
+ [:format="uint32"]
+ expected: FAIL
+
+ [:format="uint32x2"]
+ expected: FAIL
+
+ [:format="uint32x3"]
+ expected: FAIL
+
+ [:format="uint32x4"]
+ expected: FAIL
+
+ [:format="sint32"]
+ expected: FAIL
+
+ [:format="sint32x2"]
+ expected: FAIL
+
+ [:format="sint32x3"]
+ expected: FAIL
+
+ [:format="sint32x4"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,shader_module,compilation_info:compilationInfo_returns:*]
+ [:valid=true;name="ascii"]
+ expected: FAIL
+
+ [:valid=true;name="unicode"]
+ expected: FAIL
+
+ [:valid=false;name="ascii"]
+ expected: FAIL
+
+ [:valid=false;name="unicode"]
+ expected: FAIL
+
+ [:valid=false;name="carriage-return"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,uncapturederror:only_original_device_is_event_target:*]
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,correctness:discontiguous_location_and_attribs:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,texture_view,read:dimension:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,uncapturederror:iff_uncaptured:*]
+
+[cts.https.html?q=webgpu:api,operation,shader_module,compilation_info:line_number_and_position:*]
+ [:valid=false;name="ascii"]
+ expected: FAIL
+
+ [:valid=false;name="unicode"]
+ expected: FAIL
+
+ [:valid=false;name="carriage-return"]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/chunked/9/cts.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/chunked/9/cts.https.html.ini
new file mode 100644
index 0000000000..a40a461aee
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/chunked/9/cts.https.html.ini
@@ -0,0 +1,588 @@
+[cts.https.html?q=webgpu:api,validation,buffer,destroy:while_mapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,state,destroyed:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:index_format,setIndexBuffer_before_setPipeline:*]
+ [:setIndexBufferBeforeSetPipeline=false]
+ expected: FAIL
+
+ [:setIndexBufferBeforeSetPipeline=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:index_format,uint32:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,usage:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,create:size:*]
+ [:mappedAtCreation=false]
+ expected: FAIL
+
+ [:mappedAtCreation=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mapped:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,invalidBuffer:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,create:usage:*]
+ [:usage1=0;usage2=0]
+ expected: FAIL
+
+ [:usage1=0;usage2=1]
+ expected: FAIL
+
+ [:usage1=0;usage2=2]
+ expected: FAIL
+
+ [:usage1=0;usage2=4]
+ expected: FAIL
+
+ [:usage1=0;usage2=8]
+ expected: FAIL
+
+ [:usage1=0;usage2=16]
+ expected: FAIL
+
+ [:usage1=0;usage2=32]
+ expected: FAIL
+
+ [:usage1=0;usage2=64]
+ expected: FAIL
+
+ [:usage1=0;usage2=128]
+ expected: FAIL
+
+ [:usage1=0;usage2=256]
+ expected: FAIL
+
+ [:usage1=0;usage2=512]
+ expected: FAIL
+
+ [:usage1=0;usage2=32768]
+ expected: FAIL
+
+ [:usage1=1;usage2=0]
+ expected: FAIL
+
+ [:usage1=1;usage2=1]
+ expected: FAIL
+
+ [:usage1=1;usage2=2]
+ expected: FAIL
+
+ [:usage1=1;usage2=4]
+ expected: FAIL
+
+ [:usage1=1;usage2=8]
+ expected: FAIL
+
+ [:usage1=1;usage2=16]
+ expected: FAIL
+
+ [:usage1=1;usage2=32]
+ expected: FAIL
+
+ [:usage1=1;usage2=64]
+ expected: FAIL
+
+ [:usage1=1;usage2=128]
+ expected: FAIL
+
+ [:usage1=1;usage2=256]
+ expected: FAIL
+
+ [:usage1=1;usage2=512]
+ expected: FAIL
+
+ [:usage1=1;usage2=32768]
+ expected: FAIL
+
+ [:usage1=2;usage2=0]
+ expected: FAIL
+
+ [:usage1=2;usage2=1]
+ expected: FAIL
+
+ [:usage1=2;usage2=2]
+ expected: FAIL
+
+ [:usage1=2;usage2=4]
+ expected: FAIL
+
+ [:usage1=2;usage2=8]
+ expected: FAIL
+
+ [:usage1=2;usage2=16]
+ expected: FAIL
+
+ [:usage1=2;usage2=32]
+ expected: FAIL
+
+ [:usage1=2;usage2=64]
+ expected: FAIL
+
+ [:usage1=2;usage2=128]
+ expected: FAIL
+
+ [:usage1=2;usage2=256]
+ expected: FAIL
+
+ [:usage1=2;usage2=512]
+ expected: FAIL
+
+ [:usage1=2;usage2=32768]
+ expected: FAIL
+
+ [:usage1=4;usage2=0]
+ expected: FAIL
+
+ [:usage1=4;usage2=1]
+ expected: FAIL
+
+ [:usage1=4;usage2=2]
+ expected: FAIL
+
+ [:usage1=4;usage2=4]
+ expected: FAIL
+
+ [:usage1=4;usage2=8]
+ expected: FAIL
+
+ [:usage1=4;usage2=16]
+ expected: FAIL
+
+ [:usage1=4;usage2=32]
+ expected: FAIL
+
+ [:usage1=4;usage2=64]
+ expected: FAIL
+
+ [:usage1=4;usage2=128]
+ expected: FAIL
+
+ [:usage1=4;usage2=256]
+ expected: FAIL
+
+ [:usage1=4;usage2=512]
+ expected: FAIL
+
+ [:usage1=4;usage2=32768]
+ expected: FAIL
+
+ [:usage1=8;usage2=0]
+ expected: FAIL
+
+ [:usage1=8;usage2=1]
+ expected: FAIL
+
+ [:usage1=8;usage2=2]
+ expected: FAIL
+
+ [:usage1=8;usage2=4]
+ expected: FAIL
+
+ [:usage1=8;usage2=8]
+ expected: FAIL
+
+ [:usage1=8;usage2=16]
+ expected: FAIL
+
+ [:usage1=8;usage2=32]
+ expected: FAIL
+
+ [:usage1=8;usage2=64]
+ expected: FAIL
+
+ [:usage1=8;usage2=128]
+ expected: FAIL
+
+ [:usage1=8;usage2=256]
+ expected: FAIL
+
+ [:usage1=8;usage2=512]
+ expected: FAIL
+
+ [:usage1=8;usage2=32768]
+ expected: FAIL
+
+ [:usage1=16;usage2=0]
+ expected: FAIL
+
+ [:usage1=16;usage2=1]
+ expected: FAIL
+
+ [:usage1=16;usage2=2]
+ expected: FAIL
+
+ [:usage1=16;usage2=4]
+ expected: FAIL
+
+ [:usage1=16;usage2=8]
+ expected: FAIL
+
+ [:usage1=16;usage2=16]
+ expected: FAIL
+
+ [:usage1=16;usage2=32]
+ expected: FAIL
+
+ [:usage1=16;usage2=64]
+ expected: FAIL
+
+ [:usage1=16;usage2=128]
+ expected: FAIL
+
+ [:usage1=16;usage2=256]
+ expected: FAIL
+
+ [:usage1=16;usage2=512]
+ expected: FAIL
+
+ [:usage1=16;usage2=32768]
+ expected: FAIL
+
+ [:usage1=32;usage2=0]
+ expected: FAIL
+
+ [:usage1=32;usage2=1]
+ expected: FAIL
+
+ [:usage1=32;usage2=2]
+ expected: FAIL
+
+ [:usage1=32;usage2=4]
+ expected: FAIL
+
+ [:usage1=32;usage2=8]
+ expected: FAIL
+
+ [:usage1=32;usage2=16]
+ expected: FAIL
+
+ [:usage1=32;usage2=32]
+ expected: FAIL
+
+ [:usage1=32;usage2=64]
+ expected: FAIL
+
+ [:usage1=32;usage2=128]
+ expected: FAIL
+
+ [:usage1=32;usage2=256]
+ expected: FAIL
+
+ [:usage1=32;usage2=512]
+ expected: FAIL
+
+ [:usage1=32;usage2=32768]
+ expected: FAIL
+
+ [:usage1=64;usage2=0]
+ expected: FAIL
+
+ [:usage1=64;usage2=1]
+ expected: FAIL
+
+ [:usage1=64;usage2=2]
+ expected: FAIL
+
+ [:usage1=64;usage2=4]
+ expected: FAIL
+
+ [:usage1=64;usage2=8]
+ expected: FAIL
+
+ [:usage1=64;usage2=16]
+ expected: FAIL
+
+ [:usage1=64;usage2=32]
+ expected: FAIL
+
+ [:usage1=64;usage2=64]
+ expected: FAIL
+
+ [:usage1=64;usage2=128]
+ expected: FAIL
+
+ [:usage1=64;usage2=256]
+ expected: FAIL
+
+ [:usage1=64;usage2=512]
+ expected: FAIL
+
+ [:usage1=64;usage2=32768]
+ expected: FAIL
+
+ [:usage1=128;usage2=0]
+ expected: FAIL
+
+ [:usage1=128;usage2=1]
+ expected: FAIL
+
+ [:usage1=128;usage2=2]
+ expected: FAIL
+
+ [:usage1=128;usage2=4]
+ expected: FAIL
+
+ [:usage1=128;usage2=8]
+ expected: FAIL
+
+ [:usage1=128;usage2=16]
+ expected: FAIL
+
+ [:usage1=128;usage2=32]
+ expected: FAIL
+
+ [:usage1=128;usage2=64]
+ expected: FAIL
+
+ [:usage1=128;usage2=128]
+ expected: FAIL
+
+ [:usage1=128;usage2=256]
+ expected: FAIL
+
+ [:usage1=128;usage2=512]
+ expected: FAIL
+
+ [:usage1=128;usage2=32768]
+ expected: FAIL
+
+ [:usage1=256;usage2=0]
+ expected: FAIL
+
+ [:usage1=256;usage2=1]
+ expected: FAIL
+
+ [:usage1=256;usage2=2]
+ expected: FAIL
+
+ [:usage1=256;usage2=4]
+ expected: FAIL
+
+ [:usage1=256;usage2=8]
+ expected: FAIL
+
+ [:usage1=256;usage2=16]
+ expected: FAIL
+
+ [:usage1=256;usage2=32]
+ expected: FAIL
+
+ [:usage1=256;usage2=64]
+ expected: FAIL
+
+ [:usage1=256;usage2=128]
+ expected: FAIL
+
+ [:usage1=256;usage2=256]
+ expected: FAIL
+
+ [:usage1=256;usage2=512]
+ expected: FAIL
+
+ [:usage1=256;usage2=32768]
+ expected: FAIL
+
+ [:usage1=512;usage2=0]
+ expected: FAIL
+
+ [:usage1=512;usage2=1]
+ expected: FAIL
+
+ [:usage1=512;usage2=2]
+ expected: FAIL
+
+ [:usage1=512;usage2=4]
+ expected: FAIL
+
+ [:usage1=512;usage2=8]
+ expected: FAIL
+
+ [:usage1=512;usage2=16]
+ expected: FAIL
+
+ [:usage1=512;usage2=32]
+ expected: FAIL
+
+ [:usage1=512;usage2=64]
+ expected: FAIL
+
+ [:usage1=512;usage2=128]
+ expected: FAIL
+
+ [:usage1=512;usage2=256]
+ expected: FAIL
+
+ [:usage1=512;usage2=512]
+ expected: FAIL
+
+ [:usage1=512;usage2=32768]
+ expected: FAIL
+
+ [:usage1=32768;usage2=0]
+ expected: FAIL
+
+ [:usage1=32768;usage2=1]
+ expected: FAIL
+
+ [:usage1=32768;usage2=2]
+ expected: FAIL
+
+ [:usage1=32768;usage2=4]
+ expected: FAIL
+
+ [:usage1=32768;usage2=8]
+ expected: FAIL
+
+ [:usage1=32768;usage2=16]
+ expected: FAIL
+
+ [:usage1=32768;usage2=32]
+ expected: FAIL
+
+ [:usage1=32768;usage2=64]
+ expected: FAIL
+
+ [:usage1=32768;usage2=128]
+ expected: FAIL
+
+ [:usage1=32768;usage2=256]
+ expected: FAIL
+
+ [:usage1=32768;usage2=512]
+ expected: FAIL
+
+ [:usage1=32768;usage2=32768]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappingPending:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeAlignment:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,create:limit:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,earlyRejection:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeOOB:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,create:createBuffer_invalid_and_oom:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappedAtCreation:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:index_format,change_pipeline_after_setIndexBuffer:*]
+ [:setPipelineBeforeSetIndexBuffer=false]
+ expected: FAIL
+
+ [:setPipelineBeforeSetIndexBuffer=true]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,destroy:twice:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:primitive_restart:*]
+ [:indexFormat="uint16";primitiveTopology="point-list"]
+ expected: FAIL
+
+ [:indexFormat="uint16";primitiveTopology="line-list"]
+ expected: FAIL
+
+ [:indexFormat="uint16";primitiveTopology="line-strip"]
+ expected: FAIL
+
+ [:indexFormat="uint16";primitiveTopology="triangle-list"]
+ expected: FAIL
+
+ [:indexFormat="uint16";primitiveTopology="triangle-strip"]
+ expected: FAIL
+
+ [:indexFormat="uint32";primitiveTopology="point-list"]
+ expected: FAIL
+
+ [:indexFormat="uint32";primitiveTopology="line-list"]
+ expected: FAIL
+
+ [:indexFormat="uint32";primitiveTopology="line-strip"]
+ expected: FAIL
+
+ [:indexFormat="uint32";primitiveTopology="triangle-list"]
+ expected: FAIL
+
+ [:indexFormat="uint32";primitiveTopology="triangle-strip"]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,destroy:all_usages:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:index_format,setIndexBuffer_different_formats:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,abort_over_invalid_error:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,mapping:mapAsync,sizeUnspecifiedOOB:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,operation,vertex_state,index_format:index_format,uint16:*]
+ [:]
+ expected: FAIL
+
+
+[cts.https.html?q=webgpu:api,validation,buffer,destroy:error_buffer:*]
+ [:]
+ expected: FAIL
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/__dir__.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/__dir__.ini
new file mode 100644
index 0000000000..9b96fd454b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/__dir__.ini
@@ -0,0 +1,4 @@
+# These tests have issues on Windows, for now.
+# See <https://bugzilla.mozilla.org/show_bug.cgi?id=1824042>.
+disabled:
+ if os == "win": true
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html.ini
new file mode 100644
index 0000000000..2ec1f1a89b
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_clear.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html.ini
new file mode 100644
index 0000000000..cf5da7cef4
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_colorspace_bgra8unorm.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html.ini
new file mode 100644
index 0000000000..9a81754e50
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_colorspace_rgba16float.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html.ini
new file mode 100644
index 0000000000..b50b053d48
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_colorspace_rgba8unorm.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html.ini
new file mode 100644
index 0000000000..12888843fe
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_bgra8unorm_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html.ini
new file mode 100644
index 0000000000..9d227bd4b2
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_bgra8unorm_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html.ini
new file mode 100644
index 0000000000..4f9c1fc364
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba16float_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html.ini
new file mode 100644
index 0000000000..6aab6528a9
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba16float_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html.ini
new file mode 100644
index 0000000000..2c13269b3e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba16float_store.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html.ini
new file mode 100644
index 0000000000..a7770959ae
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba8unorm_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html.ini
new file mode 100644
index 0000000000..a18787d803
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba8unorm_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html.ini
new file mode 100644
index 0000000000..c13a567bd9
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_complex_rgba8unorm_store.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html.ini
new file mode 100644
index 0000000000..9d3b9009c4
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_bgra8unorm_opaque_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html.ini
new file mode 100644
index 0000000000..f0d47b0215
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_bgra8unorm_opaque_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html.ini
new file mode 100644
index 0000000000..cd4cd1e53c
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html.ini
new file mode 100644
index 0000000000..09abd6876d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html.ini
new file mode 100644
index 0000000000..4190ac446d
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba16float_opaque_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html.ini
new file mode 100644
index 0000000000..3ad85da88e
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba16float_opaque_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html.ini
new file mode 100644
index 0000000000..2685168c86
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba16float_premultiplied_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html.ini
new file mode 100644
index 0000000000..1f8f534bf8
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba16float_premultiplied_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html.ini
new file mode 100644
index 0000000000..eea7e5f4ea
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba8unorm_opaque_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html.ini
new file mode 100644
index 0000000000..12831f6756
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba8unorm_opaque_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html.ini
new file mode 100644
index 0000000000..0e2ae0415f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html.ini
new file mode 100644
index 0000000000..030a72eb69
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html.ini
new file mode 100644
index 0000000000..b64101496f
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html.ini
@@ -0,0 +1,2 @@
+[canvas_image_rendering.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/resize_observer.https.html.ini b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/resize_observer.https.html.ini
new file mode 100644
index 0000000000..259fb22346
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webgpu/webgpu/web_platform/reftests/resize_observer.https.html.ini
@@ -0,0 +1,2 @@
+[resize_observer.https.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/webtransport/__dir__.ini b/testing/web-platform/mozilla/meta/webtransport/__dir__.ini
new file mode 100644
index 0000000000..a36ddc4a41
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/webtransport/__dir__.ini
@@ -0,0 +1,4 @@
+prefs: [network.webtransport.enabled:true, network.webtransport.datagrams.enabled:true, security.OCSP.enabled:0]
+# OCSP is disabled for this directory because we get errors from attempts to access the internet with it on
+disabled:
+ if os == "android": 1823759
diff --git a/testing/web-platform/mozilla/meta/workers/__dir__.ini b/testing/web-platform/mozilla/meta/workers/__dir__.ini
new file mode 100644
index 0000000000..4dea21a2a6
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/workers/__dir__.ini
@@ -0,0 +1 @@
+prefs: [dom.workers.testing.enabled:true]
diff --git a/testing/web-platform/mozilla/meta/workers/bug1674278-crash.html.ini b/testing/web-platform/mozilla/meta/workers/bug1674278-crash.html.ini
new file mode 100644
index 0000000000..51ccbf2b7a
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/workers/bug1674278-crash.html.ini
@@ -0,0 +1,2 @@
+[bug1674278-crash.html]
+ expected: TIMEOUT
diff --git a/testing/web-platform/mozilla/meta/workers/modules/dedicated-worker-import-csp.html.ini b/testing/web-platform/mozilla/meta/workers/modules/dedicated-worker-import-csp.html.ini
new file mode 100644
index 0000000000..14e48d4018
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/workers/modules/dedicated-worker-import-csp.html.ini
@@ -0,0 +1,7 @@
+[dedicated-worker-import-csp.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ expected: [OK, TIMEOUT]
+
+ [worker-src 'self' directive should not take effect on dynamic import.]
+ expected: [FAIL, TIMEOUT]
diff --git a/testing/web-platform/mozilla/meta/workers/modules/shared-worker-import-csp.html.ini b/testing/web-platform/mozilla/meta/workers/modules/shared-worker-import-csp.html.ini
new file mode 100644
index 0000000000..5ff7ba4683
--- /dev/null
+++ b/testing/web-platform/mozilla/meta/workers/modules/shared-worker-import-csp.html.ini
@@ -0,0 +1,14 @@
+[shared-worker-import-csp.html]
+ disabled:
+ if release_or_beta: https://bugzilla.mozilla.org/show_bug.cgi?id=1812591
+ [script-src 'self' directive should disallow cross origin dynamic import.]
+ expected: [PASS, FAIL]
+
+ [worker-src 'self' directive should not take effect on dynamic import.]
+ expected: [FAIL, TIMEOUT]
+
+ [worker-src * directive should allow cross origin static import.]
+ expected: [PASS, FAIL]
+
+ [script-src * directive should allow cross origin static import.]
+ expected: [PASS, FAIL]
diff --git a/testing/web-platform/mozilla/tests/audio-output/selectAudioOutput-user-activation-consumed.https.html b/testing/web-platform/mozilla/tests/audio-output/selectAudioOutput-user-activation-consumed.https.html
new file mode 100644
index 0000000000..01758fa179
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/audio-output/selectAudioOutput-user-activation-consumed.https.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<head>
+<title>Test selectAudioOutput() after user activation is consumed</title>
+<link rel="help" href="https://github.com/w3c/mediacapture-output/issues/107">
+</head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+'use strict';
+
+promise_test(async t => {
+ await test_driver.bless('transient activation');
+ // SpecialPowers is used to consume user activation because the only
+ // spec-compliant Gecko API that consumes user activation is
+ // navigator.share(), which is disabled on CI versions of WINNT.
+ // https://searchfox.org/mozilla-central/rev/66547980e8e8ca583473c74f207cae5bac1ed541/testing/web-platform/meta/web-share/share-consume-activation.https.html.ini#4
+ const had_transient_activation =
+ SpecialPowers.wrap(document).consumeTransientUserGestureActivation();
+ assert_true(had_transient_activation,
+ 'should have had transient activation');
+ const p = navigator.mediaDevices.selectAudioOutput();
+ // Race a settled promise to check that the returned promise is already
+ // rejected.
+ await promise_rejects_dom(
+ t, 'InvalidStateError', Promise.race([p, Promise.resolve()]),
+ 'selectAudioOutput should have returned an already-rejected promise.');
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/baselinecoverage/wpt_baselinecoverage.html b/testing/web-platform/mozilla/tests/baselinecoverage/wpt_baselinecoverage.html
new file mode 100644
index 0000000000..889ee9367f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/baselinecoverage/wpt_baselinecoverage.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>Baseline Coverage</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ test(function() {
+ assert_equals(true, true);
+ }, "Collecting basic baseline coverage for web-platform tests.");
+
+ async_test(function(t) {
+ function delayBaseline() {
+ return new Promise((c) => setTimeout(c, 30 * 1000));
+ }
+
+ delayBaseline().then(() => {
+ assert_equals(true, true);
+ t.done();
+ });
+ }, "Collecting delayed baseline coverage for web-platform tests.");
+</script>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html
new file mode 100644
index 0000000000..c420b940f8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.http.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html
new file mode 100644
index 0000000000..a7bb3de773
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/sharedworker-import.https.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html
new file mode 100644
index 0000000000..482a41186d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.http.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html
new file mode 100644
index 0000000000..4d75fa1ccc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/script-src-self/worker-import.https.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html
new file mode 100644
index 0000000000..f06c11dd78
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.http.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html
new file mode 100644
index 0000000000..1c9483fc05
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/sharedworker-import.https.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html
new file mode 100644
index 0000000000..f8a9e51557
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.http.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html
new file mode 100644
index 0000000000..7d6a82d8fc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.http-rp/worker-src-self/worker-import.https.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "http-rp",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html
new file mode 100644
index 0000000000..f66bc9ed7c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html
new file mode 100644
index 0000000000..bcd1f0f2ef
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.https.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html
new file mode 100644
index 0000000000..68a610d994
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.http.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html
new file mode 100644
index 0000000000..829e6e2b90
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/script-src-self/worker-import.https.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'script-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html
new file mode 100644
index 0000000000..4c6757c65f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.http.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="worker-src 'self'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html
new file mode 100644
index 0000000000..2655a33036
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/sharedworker-import.https.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec content-security-policy/` -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="worker-src 'self'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for sharedworker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "sharedworker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for sharedworker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html
new file mode 100644
index 0000000000..281987acfe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.http.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="worker-src 'self'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and keep-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and no-redirect redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-http origin and swap-origin redirection from http context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-http",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "http",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-http origin and swap-origin redirection from http context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html
new file mode 100644
index 0000000000..4654856ada
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/gen/top.meta/worker-src-self/worker-import.https.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!-- this is edited. We need to update it so that it is correctly generated if this gets adopted -->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <meta http-equiv="Content-Security-Policy" content="worker-src 'self'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/security-features/resources/common.sub.js"></script>
+ <script src="../../../generic/test-case.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ TestCase(
+ [
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "allowed",
+ "origin": "same-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects allowed for worker-import to same-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "keep-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and keep-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "no-redirect",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and no-redirect redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "cross-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to cross-https origin and swap-origin redirection from https context."
+ },
+ {
+ "expectation": "blocked",
+ "origin": "same-https",
+ "redirection": "swap-origin",
+ "source_context_list": [],
+ "source_scheme": "https",
+ "subresource": "worker-import",
+ "subresource_policy_deliveries": [
+ {
+ "deliveryType": "meta",
+ "key": "contentSecurityPolicy",
+ "value": 'worker-src-self'
+ }
+ ],
+ "test_description": "Content Security Policy: Expects blocked for worker-import to same-https origin and swap-origin redirection from https context."
+ }
+ ],
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/content-security-policy/generic/test-case.sub.js b/testing/web-platform/mozilla/tests/content-security-policy/generic/test-case.sub.js
new file mode 100644
index 0000000000..d9a6494dd3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/content-security-policy/generic/test-case.sub.js
@@ -0,0 +1,98 @@
+function TestCase(scenarios, sanityChecker) {
+ function runTest(scenario) {
+ sanityChecker.checkScenario(scenario, subresourceMap);
+
+ const urls = getRequestURLs(scenario.subresource,
+ scenario.origin,
+ scenario.redirection);
+
+ /** @type {Subresource} */
+ const subresource = {
+ subresourceType: scenario.subresource,
+ url: urls.testUrl,
+ policyDeliveries: scenario.subresource_policy_deliveries,
+ };
+
+ let violationEventResolve;
+ // Resolved with an array of securitypolicyviolation events.
+ const violationEventPromise = new Promise(resolve => {
+ violationEventResolve = resolve;
+ });
+
+ promise_test(async t => {
+ await xhrRequest(urls.announceUrl);
+
+ // Currently only requests from top-level Documents are tested
+ // (specified by `spec.src.json`) and thus securitypolicyviolation
+ // events are assumed to be fired on the top-level Document here.
+ // When adding non-top-level Document tests, securitypolicyviolation
+ // events should be caught in appropriate contexts.
+ const violationEvents = [];
+ const listener = e => { violationEvents.push(e); };
+ document.addEventListener('securitypolicyviolation', listener);
+
+ try {
+ // Send out the real resource request.
+ // This should tear down the key if it's not blocked.
+ const mainPromise = invokeRequest(subresource, scenario.source_context_list);
+ if (scenario.expectation === 'allowed') {
+ await mainPromise;
+ } else {
+ await mainPromise
+ .then(t.unreached_func('main promise resolved unexpectedly'))
+ .catch(_ => {});
+ }
+ } finally {
+ // Always perform post-processing/clean up for
+ // 'securitypolicyviolation' events and resolve
+ // `violationEventPromise`, to prevent timeout of the
+ // promise_test() below.
+
+ // securitypolicyviolation events are fired in a queued task in
+ // https://w3c.github.io/webappsec-csp/#report-violation
+ // so wait for queued tasks to run using setTimeout().
+ let timeout = 0;
+ if (scenario.subresource.startsWith('worklet-') &&
+ navigator.userAgent.includes("Firefox/")) {
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1808911
+ // In Firefox sometimes violations from Worklets are delayed.
+ timeout = 10;
+ }
+ await new Promise(resolve => setTimeout(resolve, timeout));
+
+ // Pass violation events to `violationEventPromise` (which will be tested
+ // in the subsequent promise_test()) and clean up the listener.
+ violationEventResolve(violationEvents);
+ document.removeEventListener('securitypolicyviolation', listener);
+ }
+
+ // Send request to check if the key has been torn down.
+ const assertResult = await xhrRequest(urls.assertUrl);
+
+ // Now check if the value has been torn down. If it's still there,
+ // we have blocked the request by content security policy.
+ assert_equals(assertResult.status, scenario.expectation,
+ "The resource request should be '" + scenario.expectation + "'.");
+
+ }, scenario.test_description);
+
+ promise_test(async _ => {
+ const violationEvents = await violationEventPromise;
+ if (scenario.expectation === 'allowed') {
+ assert_array_equals(violationEvents, [],
+ 'no violation events should be fired');
+ } else {
+ assert_equals(violationEvents.length, 1,
+ 'One violation event should be fired');
+ }
+ }, scenario.test_description + ": securitypolicyviolation");
+ } // runTest
+
+ function runTests() {
+ for (const scenario of scenarios) {
+ runTest(scenario);
+ }
+ }
+
+ return {start: runTests};
+}
diff --git a/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-document-reflow-count.html b/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-document-reflow-count.html
new file mode 100644
index 0000000000..69c1c4b7dd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-document-reflow-count.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Contain: Test content-visibility:hidden reflow counts</title>
+ <link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <body style="content-visibility: hidden;">
+ hello
+ </body>
+
+ <script>
+ let gUtils = SpecialPowers.getDOMWindowUtils(window);
+ let gTestContainer = document.getElementById("test");
+
+ function flushLayout() {
+ document.documentElement.offsetHeight;
+ }
+
+ function getReflowCount() {
+ flushLayout();
+ return gUtils.framesReflowed;
+ }
+
+ function runTestFunctionAndCountReflows(testFunction) {
+ const beforeCount = getReflowCount();
+ testFunction();
+ const afterCount = getReflowCount();
+ console.log(afterCount - beforeCount);
+ return afterCount - beforeCount;
+ }
+
+ test(() => {
+ flushLayout();
+
+ const reflows = runTestFunctionAndCountReflows(() => {
+ document.body.innerText = "something else";
+ });
+ assert_equals(reflows, 1, "Reflow only triggered on body.");
+ }, "Changing text of 'content-visibility: hidden' body only triggers a single reflow.");
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-reflow-count.html b/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-reflow-count.html
new file mode 100644
index 0000000000..c1484d9c54
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/css-contain/content-visibility-hidden-reflow-count.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Contain: Test content-visibility:hidden reflow counts</title>
+ <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1746098">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <style>
+ .container {
+ content-visibility: visible;
+ contain: strict;
+ }
+ .flex {
+ display: flex;
+ }
+ .grid {
+ display: grid;
+ grid: repeat(2, 60px) / auto-flow 80px;
+ }
+ </style>
+
+ <div id="test"></div>
+
+ <script>
+ let gUtils = SpecialPowers.getDOMWindowUtils(window);
+ let gTestContainer = document.getElementById("test");
+
+ function setupContainerWithStrictContainment() {
+ const container = document.createElement("div");
+ container.classList.add("container");
+ gTestContainer.innerHTML = "";
+ gTestContainer.appendChild(container);
+ return container;
+ }
+
+ function flushLayout() {
+ document.documentElement.offsetHeight;
+ }
+
+ function getReflowCount() {
+ flushLayout();
+ return gUtils.framesReflowed;
+ }
+
+ function runTestFunctionAndCountReflows(testFunction, container) {
+ const beforeCount = getReflowCount();
+ testFunction(container);
+ const afterCount = getReflowCount();
+ return afterCount - beforeCount;
+ }
+
+ function assertContentVisibilityHiddenHasFewerReflows(testSetup, testFunction) {
+ let container = setupContainerWithStrictContainment();
+ testSetup(container);
+ flushLayout();
+
+ const visibleReflows = runTestFunctionAndCountReflows(testFunction, container);
+
+ container = setupContainerWithStrictContainment();
+ testSetup(container);
+ container.style.contentVisibility = "hidden";
+ flushLayout();
+
+ const hiddenReflows = runTestFunctionAndCountReflows(testFunction, container);
+ assert_less_than(hiddenReflows, visibleReflows,
+ "Style / layout changes in hidden content resulted in fewer reflows than visible content.");
+ }
+
+ test(() => {
+ assertContentVisibilityHiddenHasFewerReflows(
+ (container) => {
+ const div = document.createElement("div");
+ div.innerText = "Test Content";
+ container.appendChild(div);
+ },
+ (container) => {
+ container.children[0].style.width = "100px";
+ container.children[0].style.height = "100px";
+ });
+ }, `Avoiding layout while modifying a simple div's style.`);
+
+ test(() => {
+ assertContentVisibilityHiddenHasFewerReflows(
+ (container) => {
+ container.classList.add("flex");
+
+ const flexContainer = document.createElement("div");
+ flexContainer.classList.add("flex");
+ container.appendChild(flexContainer);
+
+ container.appendChild(document.createElement("div"));
+ },
+ (container) => {
+ container.children[0].style.flexDirection = "row-reverse";
+ }
+ );
+ }, `Avoiding layout while modifying a div with flex display mode.`);
+
+ test(() => {
+ assertContentVisibilityHiddenHasFewerReflows(
+ (container) => {
+ container.classList.add("grid");
+
+ const gridChild = document.createElement("div");
+ gridChild.style.display = "grid";
+ container.appendChild(gridChild);
+
+ container.appendChild(document.createElement("div"));
+ },
+ (container) => {
+ container.children[0].style.rowGap = "30px";
+ },
+ );
+ }, `Avoiding layout while modifying a div with grid display mode.`);
+
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html b/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html
new file mode 100644
index 0000000000..aa4ed4667b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/css-overflow/scrollbar-gutter-reflow-counts-001.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Overflow: Test scrollbar-gutter reflow counts</title>
+ <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1746098">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <style>
+ #target {
+ inline-size: 200px;
+ block-size: 100px;
+ background: lightgray;
+ overflow: auto;
+ }
+
+ #targetChild {
+ inline-size: 100%;
+ block-size: 100%;
+ background: orange;
+ }
+ </style>
+
+ <p>Here is a scroll contaier for testing:</p>
+ <div id="target">
+ <div id="targetChild"></div>
+ </div>
+
+ <script>
+ let gUtils = SpecialPowers.getDOMWindowUtils(window);
+ let gTarget = document.getElementById("target");
+ let gTargetChild = document.getElementById("targetChild");
+
+ function getReflowCount()
+ {
+ document.documentElement.offsetHeight; // flush layout
+ return gUtils.framesReflowed;
+ }
+
+ function cleanUp() {
+ gTarget.style.writingMode = "";
+ gTarget.style.scrollbarGutter = "";
+ gTargetChild.style.blockSize = "";
+ }
+
+ function tweakStyleAndCountReflows(aAddStyle, aAddScrollbarGutter)
+ {
+ let beforeCount = getReflowCount();
+ if (aAddScrollbarGutter) {
+ gTarget.style.scrollbarGutter = "stable";
+ }
+ aAddStyle();
+ let afterCount = getReflowCount();
+ cleanUp();
+
+ let numReflows = afterCount - beforeCount;
+ assert_greater_than(numReflows, 0, "We should've reflowed *something* after changing styles:");
+ return numReflows;
+ }
+
+ let gTestCases = [
+ {
+ name : "Enlarge the child's block-size to 200%",
+ addStyle : function () {
+ gTargetChild.style.blockSize = "200%";
+ },
+ },
+ {
+ name : "Enlarge the child's block-size to 300px",
+ addStyle : function () {
+ gTargetChild.style.blockSize = "300px";
+ },
+ },
+ {
+ name : "Enlarge the child's block-size to 200% in a vertical-lr scroll container",
+ addStyle : function () {
+ gTarget.style.writingMode = "vertical-lr";
+ gTargetChild.style.blockSize = "200%";
+ },
+ },
+ {
+ name : "Enlarge the child's block-size to 300px in a vertical-lr scroll container",
+ addStyle : function () {
+ gTarget.style.writingMode = "vertical-lr";
+ gTargetChild.style.blockSize = "300px";
+ },
+ },
+ {
+ name : "Enlarge the child's block-size to 200% in a vertical-rl scroll container",
+ addStyle : function () {
+ gTarget.style.writingMode = "vertical-rl";
+ gTargetChild.style.blockSize = "200%";
+ },
+ },
+ {
+ name : "Enlarge the child's block-size to 300px in a vertical-rl scroll container",
+ addStyle : function () {
+ gTarget.style.writingMode = "vertical-rl";
+ gTargetChild.style.blockSize = "300px";
+ },
+ },
+ ];
+
+ for (let testcase of gTestCases) {
+ test(function () {
+ let numTestReflows = tweakStyleAndCountReflows(testcase.addStyle, true);
+ let numReferenceReflows = tweakStyleAndCountReflows(testcase.addStyle, false);
+ assert_less_than(numTestReflows, numReferenceReflows,
+ "A scroll container with 'scrollbar-gutter:stable' should have less reflow counts:");
+ }, testcase.name)
+ }
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print-ref.html b/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print-ref.html
new file mode 100644
index 0000000000..1fc00e7e39
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print-ref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<div>PASS</div>
diff --git a/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print.html b/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print.html
new file mode 100644
index 0000000000..8e9172956c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/cssom/media-print-change-print.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<link rel=match href="media-print-change-print-ref.html">
+<div id="target">FAIL</div>
+<script>
+ matchMedia("print").addEventListener("change", function() {
+ document.getElementById("target").innerHTML = "PASS";
+ });
+</script>
diff --git a/testing/web-platform/mozilla/tests/css/cssom/window_size_rounding.html b/testing/web-platform/mozilla/tests/css/cssom/window_size_rounding.html
new file mode 100644
index 0000000000..695bf8f34b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/cssom/window_size_rounding.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<pre>
+<script>
+test(function() {
+ let originalWidth = window.innerWidth;
+ let originalHeight = window.innerHeight;
+
+ assert_equals(window.devicePixelRatio, 1, `precondition: ${originalWidth}x${originalHeight}`);
+
+ // This precondition holds because of:
+ // https://searchfox.org/mozilla-central/rev/50215d649d4854812837f1343e8f47bd998dacb5/browser/base/content/browser.js#1717
+ //
+ // But if this test starts failing you can just update the assert and the
+ // factor below accordingly so that the asserts keep passing.
+ assert_equals(originalWidth, 1280, "precondition");
+
+ // Set a fractional scale factor that guarantees that we get a fractional innerWidth
+ const kFactor = 1.5;
+ const kOneAppUnit = 1 / 60;
+
+ SpecialPowers.setFullZoom(window, kFactor);
+ assert_approx_equals(window.devicePixelRatio, kFactor, kOneAppUnit);
+ assert_not_equals(window.innerWidth, originalWidth);
+ assert_not_equals(window.innerHeight, originalHeight);
+ if (SpecialPowers.getBoolPref("dom.innerSize.rounded")) {
+ assert_equals(window.innerWidth, Math.round(originalWidth / kFactor));
+ assert_equals(window.innerHeight, Math.round(originalHeight / kFactor));
+ } else {
+ assert_not_equals(window.innerWidth, Math.round(window.innerWidth));
+ }
+ SpecialPowers.setFullZoom(window, 1); // Restore zoom so results can be seen fine...
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/css/file-selector-button-margin-notref.html b/testing/web-platform/mozilla/tests/css/file-selector-button-margin-notref.html
new file mode 100644
index 0000000000..67fc0af389
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/file-selector-button-margin-notref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<input type=file>
diff --git a/testing/web-platform/mozilla/tests/css/file-selector-button-margin.html b/testing/web-platform/mozilla/tests/css/file-selector-button-margin.html
new file mode 100644
index 0000000000..46c1bd0e3e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/file-selector-button-margin.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>CSS Test: margin can be used to shrink the spacing between the file selector button and its label</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1673895">
+<link rel="mismatch" href="file-selector-margin-notref.html">
+<style>
+::file-selector-button {
+ margin: 0;
+}
+</style>
+<input type=file>
diff --git a/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print-ref.html b/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print-ref.html
new file mode 100644
index 0000000000..ad2922d8a1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<style>
+ body { margin: 0 }
+</style>
+<iframe frameborder=0 scrolling=no src="resources/iframe-os-text-scale-inner.html"></iframe>
diff --git a/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print.sub.html b/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print.sub.html
new file mode 100644
index 0000000000..d0647da9b3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/iframe-os-text-scale-print.sub.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<link rel=match href="iframe-os-text-scale-print-ref.html">
+<style>
+ body { margin: 0 }
+</style>
+<iframe frameborder=0 scrolling=no src="//{{hosts[alt][www]}}:{{ports[http][0]}}{{location[path]}}/../resources/iframe-os-text-scale-inner.html"></iframe>
diff --git a/testing/web-platform/mozilla/tests/css/mediaqueries/mq-gamut-resist-fingerprinting.html b/testing/web-platform/mozilla/tests/css/mediaqueries/mq-gamut-resist-fingerprinting.html
new file mode 100644
index 0000000000..06424705ac
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/mediaqueries/mq-gamut-resist-fingerprinting.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Test: color-gamut only matches sRGB when resisting fingerprinting</title>
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<!--
+ This test is trivial as long as Firefox only matches the sRGB color-gamut media
+ query. Once Firefox can match additional color-gamuts, though, we should still
+ only match sRGB when resisting fingerprinting.
+-->
+<style>
+div {
+ width: 100px;
+ height: 100px;
+}
+
+div.with-gamut {
+ background-color: red;
+}
+
+div.without-gamuts {
+ background-color: green;
+}
+
+@media (color-gamut: srgb) {
+ div.with-gamut {
+ background-color: green;
+ }
+}
+
+@media (color-gamut: p3), (color-gamut: rec2020) {
+ div.without-gamuts {
+ background-color: red;
+ }
+}
+</style>
+
+<p>Test passes if there are two filled green squares and <strong>no red</strong>.
+
+<div class=with-gamut></div>
+<p></p>
+<div class=without-gamuts></div>
diff --git a/testing/web-platform/mozilla/tests/css/quirks-invalidation-standard-sheet.html b/testing/web-platform/mozilla/tests/css/quirks-invalidation-standard-sheet.html
new file mode 100644
index 0000000000..b926f81af4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/quirks-invalidation-standard-sheet.html
@@ -0,0 +1,14 @@
+<!-- quirks, intentionally -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div class="mixedCase"></div>
+<script>
+ test(function() {
+ const kLime = "rgb(0, 255, 0)";
+
+ let div = document.querySelector("div");
+ assert_not_equals(getComputedStyle(div).color, kLime);
+ SpecialPowers.DOMWindowUtils.loadSheetUsingURIString('data:text/css,.mixedCase{color:lime}', 1)
+ assert_equals(getComputedStyle(div).color, kLime);
+ }, "Invalidation of quirks documents when standard sheets are inserted works properly")
+</script>
diff --git a/testing/web-platform/mozilla/tests/css/reference/ref-filled-green-100px-square.xht b/testing/web-platform/mozilla/tests/css/reference/ref-filled-green-100px-square.xht
new file mode 100644
index 0000000000..9b647491e9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/reference/ref-filled-green-100px-square.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Reftest Reference</title>
+ <style type="text/css"><![CDATA[
+ div {
+ background-color: green;
+ height: 100px;
+ width: 100px;
+ }
+ ]]></style>
+ </head>
+ <body>
+ <p>Test passes if there are two filled green squares and <strong>no red</strong>.</p>
+ <div></div>
+ <p></p>
+ <div></div>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/css/resources/iframe-os-text-scale-inner.html b/testing/web-platform/mozilla/tests/css/resources/iframe-os-text-scale-inner.html
new file mode 100644
index 0000000000..be51cc957c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/css/resources/iframe-os-text-scale-inner.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<style>
+body {
+ background-color: green;
+ height: 100vh;
+ width: 100vw;
+}
+</style>
+TEST
diff --git a/testing/web-platform/mozilla/tests/dom/classList.html b/testing/web-platform/mozilla/tests/dom/classList.html
new file mode 100644
index 0000000000..21d79f49e3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/classList.html
@@ -0,0 +1,526 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for the classList element attribute</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="content"></div>
+<script>
+// This should be the same as dom/nodes/Element-classlist.html in the upstream
+// tests! We have a couple of bits changed, which are marked with comments
+// "LOCAL MODIFICATION". Do not change this without changing the upstream test
+// as well! Merging upstream changes here occasionally might also be nice.
+
+const SVG_NS = "http://www.w3.org/2000/svg";
+const XHTML_NS = "http://www.w3.org/1999/xhtml"
+const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
+
+// BEGIN LOCAL MODIFICATION: The spec does not have the onAttrModified event
+// and does not want it, but we still support it.
+var gMutationEvents = [];
+
+function onAttrModified(event) {
+ assert_equals(event.attrName, "class", "mutation on unexpected attribute");
+
+ gMutationEvents.push({
+ attrChange: event.attrChange,
+ prevValue: event.prevValue,
+ newValue: event.newValue,
+ });
+}
+// END LOCAL MODIFICATION
+
+function setClass(e, newVal) {
+ if (newVal === null) {
+ e.removeAttribute("class");
+ } else {
+ e.setAttribute("class", newVal);
+ }
+}
+
+function checkModification(e, funcName, args, expectedRes, before, after,
+ expectedException, desc) {
+ if (!Array.isArray(args)) {
+ args = [args];
+ }
+
+ test(function() {
+ var shouldThrow = typeof(expectedException) === "string";
+ if (shouldThrow) {
+ // If an exception is thrown, the class attribute shouldn't change.
+ after = before;
+ }
+ setClass(e, before);
+
+ // BEGIN LOCAL MODIFICATION
+ gMutationEvents = [];
+ e.addEventListener("DOMAttrModified", onAttrModified);
+ // END LOCAL MODIFICATION
+ var obs;
+ // If we have MutationObservers available, do some checks to make
+ // sure attribute sets are happening at sane times.
+ if (self.MutationObserver) {
+ obs = new MutationObserver(() => {});
+ obs.observe(e, { attributes: true });
+ }
+ if (shouldThrow) {
+ assert_throws_dom(expectedException, function() {
+ var list = e.classList;
+ var res = list[funcName].apply(list, args);
+ });
+ } else {
+ var list = e.classList;
+ var res = list[funcName].apply(list, args);
+ }
+ if (obs) {
+ var mutationRecords = obs.takeRecords();
+ obs.disconnect();
+ if (shouldThrow) {
+ assert_equals(mutationRecords.length, 0,
+ "There should have been no mutation");
+ } else if (funcName == "replace") {
+ assert_equals(mutationRecords.length == 1,
+ expectedRes,
+ "Should have a mutation exactly when replace() returns true");
+ } else {
+ // For other functions, would need to check when exactly
+ // mutations are supposed to happen.
+ }
+ }
+ // BEGIN LOCAL MODIFICATION
+ e.removeEventListener("DOMAttrModified", onAttrModified);
+ // END LOCAL MODIFICATION
+ if (!shouldThrow) {
+ assert_equals(res, expectedRes, "wrong return value");
+ }
+
+ var expectedAfter = after;
+
+ assert_equals(e.getAttribute("class"), expectedAfter,
+ "wrong class after modification");
+ // BEGIN LOCAL MODIFICATION
+ var expectedMutation = before != after;
+ assert_equals(gMutationEvents.length, expectedMutation ? 1 : 0,
+ "unexpected mutation event count");
+ if (expectedMutation && gMutationEvents.length) {
+ assert_equals(gMutationEvents[0].attrChange,
+ before == null ? MutationEvent.ADDITION
+ : MutationEvent.MODIFICATION,
+ "wrong type of attribute change");
+ // If there wasn't any previous attribute, prevValue will return an empty
+ // string.
+ var expectedPrevValue = before === null ? "" : before;
+ assert_equals(gMutationEvents[0].prevValue, expectedPrevValue,
+ "wrong previous value");
+ assert_equals(gMutationEvents[0].newValue, after, "wrong new value");
+ }
+ // END LOCAL MODIFICATION
+ }, "classList." + funcName + "(" + args.map(format_value).join(", ") +
+ ") with attribute value " + format_value(before) + desc);
+}
+
+function assignToClassListStrict(e) {
+ "use strict";
+ e.classList = "foo";
+ e.removeAttribute("class");
+}
+
+function assignToClassList(e) {
+ var expect = e.classList;
+ e.classList = "foo";
+ assert_equals(e.classList, expect,
+ "classList should be unchanged after assignment");
+ e.removeAttribute("class");
+}
+
+function testClassList(e, desc) {
+
+ // assignment
+
+ test(function() {
+ assignToClassListStrict(e);
+ assignToClassList(e);
+ }, "Assigning to classList" + desc);
+
+ // supports
+ test(function() {
+ assert_throws_js(TypeError, function() {
+ e.classList.supports("a");
+ })
+ }, ".supports() must throw TypeError" + desc);
+
+ // length attribute
+
+ function checkLength(value, length) {
+ test(function() {
+ setClass(e, value);
+ assert_equals(e.classList.length, length);
+ }, "classList.length when " +
+ (value === null ? "removed" : "set to " + format_value(value)) + desc);
+ }
+
+ checkLength(null, 0);
+ checkLength("", 0);
+ checkLength(" \t \f", 0);
+ checkLength("a", 1);
+ checkLength("a A", 2);
+ checkLength("\r\na\t\f", 1);
+ checkLength("a a", 1);
+ checkLength("a a a a a a", 1);
+ checkLength("a a b b", 2);
+ checkLength("a A B b", 4);
+ checkLength("a b c c b a a b c c", 3);
+ checkLength(" a a b", 2);
+ checkLength("a\tb\nc\fd\re f", 6);
+
+ // [Stringifies]
+
+ function checkStringifier(value, expected) {
+ test(function() {
+ setClass(e, value);
+ assert_equals(e.classList.toString(), expected);
+ }, "classList.toString() when " +
+ (value === null ? "removed" : "set to " + format_value(value)) + desc);
+ }
+
+ checkStringifier(null, "");
+ checkStringifier("foo", "foo");
+ checkStringifier(" a a b", " a a b");
+
+ // item() method
+
+ function checkItems(attributeValue, expectedValues) {
+ function checkItemFunction(index, expected) {
+ assert_equals(e.classList.item(index), expected,
+ "classList.item(" + index + ")");
+ }
+
+ function checkItemArray(index, expected) {
+ assert_equals(e.classList[index], expected, "classList[" + index + "]");
+ }
+
+ test(function() {
+ setClass(e, attributeValue);
+
+ checkItemFunction(-1, null);
+ checkItemArray(-1, undefined);
+
+ var i = 0;
+ while (i < expectedValues.length) {
+ checkItemFunction(i, expectedValues[i]);
+ checkItemArray(i, expectedValues[i]);
+ i++;
+ }
+
+ checkItemFunction(i, null);
+ checkItemArray(i, undefined);
+
+ checkItemFunction(0xffffffff, null);
+ checkItemArray(0xffffffff, undefined);
+
+ checkItemFunction(0xfffffffe, null);
+ checkItemArray(0xfffffffe, undefined);
+ }, "classList.item() when set to " + format_value(attributeValue) + desc);
+ }
+
+ checkItems(null, []);
+ checkItems("a", ["a"]);
+ checkItems("aa AA aa", ["aa", "AA"]);
+ checkItems("a b", ["a", "b"]);
+ checkItems(" a a b", ["a", "b"]);
+ checkItems("\t\n\f\r a\t\n\f\r b\t\n\f\r ", ["a", "b"]);
+
+ // contains() method
+
+ function checkContains(attributeValue, args, expectedRes) {
+ if (!Array.isArray(expectedRes)) {
+ expectedRes = Array(args.length).fill(expectedRes);
+ }
+ setClass(e, attributeValue);
+ for (var i = 0; i < args.length; i++) {
+ test(function() {
+ assert_equals(e.classList.contains(args[i]), expectedRes[i],
+ "classList.contains(\"" + args[i] + "\")");
+ }, "classList.contains(" + format_value(args[i]) + ") when set to " +
+ format_value(attributeValue) + desc);
+ }
+ }
+
+ checkContains(null, ["a", "", " "], false);
+ checkContains("", ["a"], false);
+
+ checkContains("a", ["a"], true);
+ checkContains("a", ["aa", "b", "A", "a.", "a)",, "a'", 'a"', "a$", "a~",
+ "a?", "a\\"], false);
+
+ // All "ASCII whitespace" per spec, before and after
+ checkContains("a", ["a\t", "\ta", "a\n", "\na", "a\f", "\fa", "a\r", "\ra",
+ "a ", " a"], false);
+
+ checkContains("aa AA", ["aa", "AA", "aA"], [true, true, false]);
+ checkContains("a a a", ["a", "aa", "b"], [true, false, false]);
+ checkContains("a b c", ["a", "b"], true);
+
+ checkContains("null undefined", [null, undefined], true);
+ checkContains("\t\n\f\r a\t\n\f\r b\t\n\f\r ", ["a", "b"], true);
+
+ // add() method
+
+ function checkAdd(before, argument, after, expectedException) {
+ checkModification(e, "add", argument, undefined, before, after,
+ expectedException, desc);
+ // Also check force toggle
+ // XXX https://github.com/whatwg/dom/issues/443
+ //if (!Array.isArray(argument)) {
+ // checkModification(e, "toggle", [argument, true], true, before, after,
+ // expectedException);
+ //}
+ }
+
+ checkAdd(null, "", null, "SyntaxError");
+ checkAdd(null, ["a", ""], null, "SyntaxError");
+ checkAdd(null, " ", null, "InvalidCharacterError");
+ checkAdd(null, "\ta", null, "InvalidCharacterError");
+ checkAdd(null, "a\t", null, "InvalidCharacterError");
+ checkAdd(null, "\na", null, "InvalidCharacterError");
+ checkAdd(null, "a\n", null, "InvalidCharacterError");
+ checkAdd(null, "\fa", null, "InvalidCharacterError");
+ checkAdd(null, "a\f", null, "InvalidCharacterError");
+ checkAdd(null, "\ra", null, "InvalidCharacterError");
+ checkAdd(null, "a\r", null, "InvalidCharacterError");
+ checkAdd(null, " a", null, "InvalidCharacterError");
+ checkAdd(null, "a ", null, "InvalidCharacterError");
+ checkAdd(null, ["a", " "], null, "InvalidCharacterError");
+ checkAdd(null, ["a", "aa "], null, "InvalidCharacterError");
+
+ checkAdd("a", "a", "a");
+ checkAdd("aa", "AA", "aa AA");
+ checkAdd("a b c", "a", "a b c");
+ checkAdd("a a a b", "a", "a b");
+ checkAdd(null, "a", "a");
+ checkAdd("", "a", "a");
+ checkAdd(" ", "a", "a");
+ checkAdd(" \f", "a", "a");
+ checkAdd("a", "b", "a b");
+ checkAdd("a b c", "d", "a b c d");
+ checkAdd("a b c ", "d", "a b c d");
+ checkAdd(" a a b", "c", "a b c");
+ checkAdd(" a a b", "a", "a b");
+ checkAdd("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "c", "a b c");
+
+ // multiple add
+ checkAdd("a b c ", ["d", "e"], "a b c d e");
+ checkAdd("a b c ", ["a", "a"], "a b c");
+ checkAdd("a b c ", ["d", "d"], "a b c d");
+ checkAdd("a b c a ", [], "a b c");
+ checkAdd(null, ["a", "b"], "a b");
+ checkAdd("", ["a", "b"], "a b");
+
+ checkAdd(null, null, "null");
+ checkAdd(null, undefined, "undefined");
+
+ // remove() method
+
+ function checkRemove(before, argument, after, expectedException) {
+ checkModification(e, "remove", argument, undefined, before, after,
+ expectedException, desc);
+ // Also check force toggle
+ // XXX https://github.com/whatwg/dom/issues/443
+ //if (!Array.isArray(argument)) {
+ // checkModification(e, "toggle", [argument, false], false, before, after,
+ // expectedException);
+ //}
+ }
+
+ checkRemove(null, "", null, "SyntaxError");
+ checkRemove(null, " ", null, "InvalidCharacterError");
+ checkRemove("\ta", "\ta", "\ta", "InvalidCharacterError");
+ checkRemove("a\t", "a\t", "a\t", "InvalidCharacterError");
+ checkRemove("\na", "\na", "\na", "InvalidCharacterError");
+ checkRemove("a\n", "a\n", "a\n", "InvalidCharacterError");
+ checkRemove("\fa", "\fa", "\fa", "InvalidCharacterError");
+ checkRemove("a\f", "a\f", "a\f", "InvalidCharacterError");
+ checkRemove("\ra", "\ra", "\ra", "InvalidCharacterError");
+ checkRemove("a\r", "a\r", "a\r", "InvalidCharacterError");
+ checkRemove(" a", " a", " a", "InvalidCharacterError");
+ checkRemove("a ", "a ", "a ", "InvalidCharacterError");
+ checkRemove("aa ", "aa ", null, "InvalidCharacterError");
+
+ checkRemove(null, "a", null);
+ checkRemove("", "a", "");
+ checkRemove("a b c", "d", "a b c");
+ checkRemove("a b c", "A", "a b c");
+ checkRemove(" a a a ", "a", "");
+ checkRemove("a b", "a", "b");
+ checkRemove("a b ", "a", "b");
+ checkRemove("a a b", "a", "b");
+ checkRemove("aa aa bb", "aa", "bb");
+ checkRemove("a a b a a c a a", "a", "b c");
+
+ checkRemove("a b c", "b", "a c");
+ checkRemove("aaa bbb ccc", "bbb", "aaa ccc");
+ checkRemove(" a b c ", "b", "a c");
+ checkRemove("a b b b c", "b", "a c");
+
+ checkRemove("a b c", "c", "a b");
+ checkRemove(" a b c ", "c", "a b");
+ checkRemove("a b c c c", "c", "a b");
+
+ checkRemove("a b a c a d a", "a", "b c d");
+ checkRemove("AA BB aa CC AA dd aa", "AA", "BB aa CC dd");
+
+ checkRemove("\ra\na\ta\f", "a", "");
+ checkRemove("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", "b");
+
+ // multiple remove
+ checkRemove("a b c ", ["d", "e"], "a b c");
+ checkRemove("a b c ", ["a", "b"], "c");
+ checkRemove("a b c ", ["a", "c"], "b");
+ checkRemove("a b c ", ["a", "a"], "b c");
+ checkRemove("a b c ", ["d", "d"], "a b c");
+ checkRemove("a b c ", [], "a b c");
+ checkRemove(null, ["a", "b"], null);
+ checkRemove("", ["a", "b"], "");
+ checkRemove("a a", [], "a");
+
+ checkRemove("null", null, "");
+ checkRemove("undefined", undefined, "");
+
+ // toggle() method
+
+ function checkToggle(before, argument, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", argument, expectedRes, before, after,
+ expectedException, desc);
+ }
+
+ checkToggle(null, "", null, null, "SyntaxError");
+ checkToggle(null, "aa ", null, null, "InvalidCharacterError");
+
+ checkToggle(null, "a", true, "a");
+ checkToggle("", "a", true, "a");
+ checkToggle(" ", "a", true, "a");
+ checkToggle(" \f", "a", true, "a");
+ checkToggle("a", "b", true, "a b");
+ checkToggle("a", "A", true, "a A");
+ checkToggle("a b c", "d", true, "a b c d");
+ checkToggle(" a a b", "d", true, "a b d");
+
+ checkToggle("a", "a", false, "");
+ checkToggle(" a a a ", "a", false, "");
+ checkToggle(" A A A ", "a", true, "A a");
+ checkToggle(" a b c ", "b", false, "a c");
+ checkToggle(" a b c b b", "b", false, "a c");
+ checkToggle(" a b c ", "c", false, "a b");
+ checkToggle(" a b c ", "a", false, "b c");
+ checkToggle(" a a b", "b", false, "a");
+ checkToggle("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", false, "b");
+ checkToggle("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "c", true, "a b c");
+
+ checkToggle("null", null, false, "");
+ checkToggle("", null, true, "null");
+ checkToggle("undefined", undefined, false, "");
+ checkToggle("", undefined, true, "undefined");
+
+
+ // tests for the force argument handling
+ // XXX Remove these if https://github.com/whatwg/dom/issues/443 is fixed
+
+ function checkForceToggle(before, argument, force, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", [argument, force], expectedRes, before,
+ after, expectedException, desc);
+ }
+
+ checkForceToggle("", "a", true, true, "a");
+ checkForceToggle("a", "a", true, true, "a");
+ checkForceToggle("a", "b", true, true, "a b");
+ checkForceToggle("a b", "b", true, true, "a b");
+ checkForceToggle("", "a", false, false, "");
+ checkForceToggle("a", "a", false, false, "");
+ checkForceToggle("a", "b", false, false, "a");
+ checkForceToggle("a b", "b", false, false, "a");
+
+
+ // replace() method
+ function checkReplace(before, token, newToken, expectedRes, after, expectedException) {
+ checkModification(e, "replace", [token, newToken], expectedRes, before,
+ after, expectedException, desc);
+ }
+
+ checkReplace(null, "", "a", null, null, "SyntaxError");
+ checkReplace(null, "", " ", null, null, "SyntaxError");
+ checkReplace(null, " ", "a", null, null, "InvalidCharacterError");
+ checkReplace(null, "\ta", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\t", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\na", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\n", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\fa", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\f", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\ra", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\r", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, " a", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a ", "b", null, null, "InvalidCharacterError");
+
+ checkReplace(null, "a", "", null, null, "SyntaxError");
+ checkReplace(null, " ", "", null, null, "SyntaxError");
+ checkReplace(null, "a", " ", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\ta", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\t", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\na", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\n", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\fa", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\f", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\ra", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\r", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", " a", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a ", null, null, "InvalidCharacterError");
+
+ checkReplace("a", "a", "a", true, "a");
+ checkReplace("a", "a", "b", true, "b");
+ checkReplace("a", "A", "b", false, "a");
+ checkReplace("a b", "b", "A", true, "a A");
+ checkReplace("a b", "c", "a", false, "a b");
+ checkReplace("a b c", "d", "e", false, "a b c");
+ // https://github.com/whatwg/dom/issues/443
+ checkReplace("a a a b", "a", "a", true, "a b");
+ checkReplace("a a a b", "c", "d", false, "a a a b");
+ checkReplace(null, "a", "b", false, null);
+ checkReplace("", "a", "b", false, "");
+ checkReplace(" ", "a", "b", false, " ");
+ checkReplace(" a \f", "a", "b", true, "b");
+ checkReplace("a b c", "b", "d", true, "a d c");
+ checkReplace("a b c", "c", "a", true, "a b");
+ checkReplace("c b a", "c", "a", true, "a b");
+ checkReplace("a b a", "a", "c", true, "c b");
+ checkReplace("a b a", "b", "c", true, "a c");
+ checkReplace(" a a b", "a", "c", true, "c b");
+ checkReplace(" a a b", "b", "c", true, "a c");
+ checkReplace("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", "c", true, "c b");
+ checkReplace("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "b", "c", true, "a c");
+
+ checkReplace("a null", null, "b", true, "a b");
+ checkReplace("a b", "a", null, true, "null b");
+ checkReplace("a undefined", undefined, "b", true, "a b");
+ checkReplace("a b", "a", undefined, true, "undefined b");
+}
+
+var content = document.getElementById("content");
+
+var htmlNode = document.createElement("div");
+content.appendChild(htmlNode);
+testClassList(htmlNode, " (HTML node)");
+
+var xhtmlNode = document.createElementNS(XHTML_NS, "div");
+content.appendChild(xhtmlNode);
+testClassList(xhtmlNode, " (XHTML node)");
+
+var mathMLNode = document.createElementNS(MATHML_NS, "math");
+content.appendChild(mathMLNode);
+testClassList(mathMLNode, " (MathML node)");
+
+var xmlNode = document.createElementNS(null, "foo");
+content.appendChild(xmlNode);
+testClassList(xmlNode, " (XML node with null namespace)");
+
+var fooNode = document.createElementNS("http://example.org/foo", "foo");
+content.appendChild(fooNode);
+testClassList(fooNode, " (foo node)");
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/delayed_window_print.html b/testing/web-platform/mozilla/tests/dom/delayed_window_print.html
new file mode 100644
index 0000000000..0bb9977184
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/delayed_window_print.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for delaying window.print() before load</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+let t = async_test("Delayed print before load");
+let beforePrintCalled = false;
+window.addEventListener("beforeprint", t.step_func(function() {
+ assert_false(beforePrintCalled, "Should only call beforeprint once");
+ beforePrintCalled = true;
+ assert_true(
+ !!document.getElementById("before-load"),
+ "Should show contents that get added before load"
+ );
+ assert_true(
+ !!document.getElementById("during-load"),
+ "Should show contents that get added during load"
+ );
+ setTimeout(function() { t.done(); }, 0);
+}));
+
+t.step(function() {
+ window.print();
+
+ let div = document.createElement("div");
+ div.id = "before-load";
+ document.body.appendChild(div);
+});
+
+window.addEventListener("load", t.step_func(function() {
+ window.print();
+
+ let div = document.createElement("div");
+ div.id = "during-load";
+ document.body.appendChild(div);
+}));
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html b/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html
new file mode 100644
index 0000000000..1fb70aa5b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html
@@ -0,0 +1,35 @@
+<!-- See also Bug 1679427.
+Ensure `select` event is only fired once when tab-ing to an `<input>` element.
+-->
+<!doctype html>
+<html>
+<head>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+</head>
+<body>
+ <button>Press this button and Press Tab</button><input value="abc">
+ <script>
+ promise_test(async t => {
+ await new Promise(resolve => { window.onload = resolve; });
+ const button = document.querySelector("button");
+ const input = document.querySelector("input");
+
+ let countSelectEvent = 0;
+ input.addEventListener("select", event => {
+ countSelectEvent++;
+ });
+
+ button.focus();
+ const tabKey = "\uE004";
+ await test_driver.send_keys(button, tabKey);
+ await new Promise(resolve => requestAnimationFrame(
+ () => requestAnimationFrame(resolve)
+ ));
+ assert_equals(countSelectEvent, 1, "Select event was fired more than once!");
+ }, "Select event should only be fired once.");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html b/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html
new file mode 100644
index 0000000000..5de81c866f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-actions.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<script>
+function abs(uri) {
+ return new URL(uri, window.location.href).href;
+}
+const CHILD_DOC = `
+<!doctype html>
+<script src="${abs("/resources/testdriver.js")}"></` + `script>
+<script src="${abs("/resources/testdriver-actions.js")}"></` + `script>
+<script src="${abs("/resources/testdriver-vendor.js")}"></` + `script>
+<script>
+ test_driver.set_test_context(opener);
+</` + `script>
+
+<a href>To link or not to link</a>
+
+<script>
+onload = async function() {
+ let link = document.querySelector("a");
+ link.focus();
+ let focused = document.activeElement == link;
+ let clicked = new Promise(resolve => {
+ link.addEventListener("click", resolve, { once: true });
+ });
+ const enterKey = '\\uE007';
+ await test_driver.send_keys(link, enterKey);
+ await clicked;
+ test_driver.message_test({ testResult: true, focused, clicked: true });
+};
+</` + `script>
+`
+
+promise_test(async function(t) {
+ await new Promise(resolve => {
+ window.onload = resolve;
+ })
+
+ let messagePromise = new Promise(resolve => {
+ addEventListener("message", function(msg) {
+ if (msg.data.testResult) {
+ resolve(msg);
+ }
+ });
+ });
+
+ let win = window.open("data:text/html," + escape(CHILD_DOC));
+
+ assert_true(true, "Window opened");
+ let message = await messagePromise;
+ assert_true(true, "message: " + JSON.stringify(message));
+
+ let { focused, clicked } = message.data;
+ assert_true(focused, "Link should be focusable");
+ assert_true(clicked, "Link should be keyboard activatable");
+
+ win.close();
+}, "Link to invalid URI should be focusable and keyboard activatable");
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html b/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html
new file mode 100644
index 0000000000..a37464d55a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+</head>
+
+<body>
+<span>One two</span>
+<script>
+promise_test(async function (t) {
+ await new Promise(resolve => {
+ window.onload = resolve;
+ })
+ const range = document.createRange();
+ range.setStart(document.body, 0);
+ range.setEnd(document.body, 1);
+ const highlight = new Highlight(range);
+ CSS.highlights.set("foo", highlight);
+ document.getSelection().addRange(range);
+
+ const highlightRange = highlight.entries().next().value[0];
+ const selectionRange = document.getSelection().getRangeAt(0);
+ assert_equals(
+ highlightRange,
+ selectionRange,
+ "The same range must be present in the highlight and the Selection."
+ );
+}, "Range is shared between a custom highlight and the document's Selection.");
+</script>
+</body>
+
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html b/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html
new file mode 100644
index 0000000000..7eb9dd1e40
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="throttling.js"></script>
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js b/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js
new file mode 100644
index 0000000000..280b0adc0d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js
@@ -0,0 +1,136 @@
+function waitForLoad() {
+ return new Promise(resolve => addEventListener('load', resolve))
+ .then(() => delay(10));
+}
+
+function delay(timeout) {
+ return new Promise(resolve => step_timeout(() => resolve(), 10));
+}
+
+function busy(work) {
+ return delay(10).then(() => new Promise(resolve => {
+ step_timeout(() => {
+ let end = performance.now() + work;
+ while (performance.now() < end) {
+
+ }
+
+ resolve();
+ }, 1);
+ }));
+}
+
+function getThrottlingRate(delay) {
+ return new Promise(resolve => {
+ let start = performance.now();
+ setTimeout(() => {
+ let rate = Math.floor((performance.now() - start) / delay);
+ resolve(rate);
+ }, delay);
+ });
+}
+
+function addElement(t, element, src) {
+ return new Promise((resolve, reject) => {
+ let e = document.createElement(element);
+ e.addEventListener('load', () => resolve(e));
+ if (src) {
+ e.src = src;
+ }
+ document.body.appendChild(e);
+ t.add_cleanup(() => e.remove());
+ });
+}
+
+function inFrame(t) {
+ return addElement(t, "iframe", "resources/test.html")
+ .then(frame => delay(10).then(() => Promise.resolve(frame.contentWindow)));
+}
+
+function addWebSocket(t, url) {
+ return new Promise((resolve, reject) => {
+ let socket = new WebSocket(url);
+ socket.onopen = () => {
+ t.add_cleanup(() => socket.close());
+ resolve();
+ };
+ socket.onerror = reject;
+ });
+}
+
+function addRTCPeerConnection(t) {
+ return new Promise((resolve, reject) => {
+ let connection = new RTCPeerConnection();
+ t.add_cleanup(() => {
+ connection.close()
+ });
+
+ resolve();
+ });
+}
+
+function addIndexedDB(t) {
+ return new Promise((resolve, reject) => {
+ let iDBState = {
+ running: false,
+ db: null
+ };
+
+ let req = indexedDB.open("testDB", 1);
+
+ req.onupgradeneeded = e => {
+ let db = e.target.result;
+ let store = db.createObjectStore("testOS", {keyPath: "id"});
+ let index = store.createIndex("index", ["col"]);
+ };
+
+ req.onsuccess = e => {
+ let db = iDBState.db = e.target.result;
+ let store = db.transaction("testOS", "readwrite").objectStore("testOS");
+ let ctr = 0;
+
+ iDBState.running = true;
+
+ function putLoop() {
+ if (!iDBState.running) {
+ return;
+ }
+
+ let req = store.put({id: ctr++, col: "foo"});
+ req.onsuccess = putLoop;
+
+ if (!iDBState.request) {
+ iDBState.request = req;
+ }
+ }
+
+ putLoop();
+ resolve();
+ };
+
+ t.add_cleanup(() => {
+ iDBState.running = false;
+ iDBState.db && iDBState.db.close();
+ iDBState.db = null;
+ });
+ });
+}
+
+function addWebAudio(t) {
+ return new Promise(resolve => {
+ let context = new (window.AudioContext || window.webkitAudioContext)();
+ context.onstatechange = () => (context.state === "running") && resolve();
+
+ let gain = context.createGain();
+ gain.gain.value = 0.1;
+ gain.connect(context.destination);
+
+ let webaudionode = context.createOscillator();
+ webaudionode.type = 'square';
+ webaudionode.frequency.value = 440; // value in hertz
+ webaudionode.connect(gain);
+ webaudionode.start();
+
+ t.add_cleanup(() => webaudionode.stop());
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js b/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js
new file mode 100644
index 0000000000..a1ac273a54
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js
@@ -0,0 +1,3 @@
+var __SERVER__NAME = "{{host}}";
+var __PORT = "{{ports[ws][0]}}";
+var __PATH = "echo";
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js
new file mode 100644
index 0000000000..86cefc8a81
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js
@@ -0,0 +1,10 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => busy(100)
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_greater_than(rate, 10, "Timeout wasn't throttled");
+ }), "Throttle when all budget has been used.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js
new file mode 100644
index 0000000000..3ccb35dc08
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => win.busy(100)
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_greater_than(rate, 10, "Timeout wasn't throttled");
+ }), "Throttle iframe when all budget has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js
new file mode 100644
index 0000000000..d1c38bcc12
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => busy(100)
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when all budget in parent has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js
new file mode 100644
index 0000000000..b072b51809
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => win.busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle parent when all budget in iframe has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js
new file mode 100644
index 0000000000..73c734a584
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addIndexedDB(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open IndexedDB transactions.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addIndexedDB(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open IndexedDB transactions in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addIndexedDB(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open IndexedDB transactions in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addIndexedDB(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open IndexedDB transactions in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js
new file mode 100644
index 0000000000..5cd7193788
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addWebAudio(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there is active WebAudio.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebAudio(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there is active WebAudio in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addWebAudio(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there is active WebAudio in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebAudio(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there is active WebAudio in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js
new file mode 100644
index 0000000000..2842f77e44
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addRTCPeerConnection(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open RTCPeerConnections.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addRTCPeerConnection(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open RTCPeerConnections in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addRTCPeerConnection(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open RTCPeerConnections in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addRTCPeerConnection(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open RTCPeerConnections in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js
new file mode 100644
index 0000000000..185654e04d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js
@@ -0,0 +1,37 @@
+// META: script=resources/ws.sub.js
+// META: script=resources/throttling.js
+let server = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addWebSocket(t, server)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open WebSockets.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebSocket(t, server))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open WebSockets in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addWebSocket(t, server)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open WebSockets in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebSocket(t, server)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open WebSockets in iframe.");
diff --git a/testing/web-platform/mozilla/tests/editor/delete-space-after-double-click-selection.html b/testing/web-platform/mozilla/tests/editor/delete-space-after-double-click-selection.html
new file mode 100644
index 0000000000..6c065cbc12
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/editor/delete-space-after-double-click-selection.html
@@ -0,0 +1,278 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="timeout" content="long">
+ <title>Test for Bug 1783641</title>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <style>
+ .testStyle {
+ font-family: 'Courier New', Courier, monospace;
+ font-size: 12px;
+ padding: 0px;
+ width: 200px;
+ }
+ </style>
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1783641">Mozilla Bug 1783641</a><br />
+ <span class="testStyle" id="placeholder"></span>
+ <input class="testStyle" type="text" />
+ <div class="testStyle" contenteditable></div>
+ <textarea class="testStyle"></textarea>
+ <script>
+
+ promise_test(async t => {
+ await new Promise(resolve => { window.onload = resolve; });
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["editor.word_select.delete_space_after_doubleclick_selection", true],
+ ["layout.word_select.eat_space_to_next_word", false]
+ ]
+ });
+ }, "Test setup");
+ const placeHolder = document.getElementById("placeholder");
+ const deleteKey = "\uE017";
+
+ function waitForRender() {
+ return new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
+ };
+
+ for (const selector of ["input", "div[contenteditable]", "textarea"]) {
+ const editableElement = document.querySelector(selector);
+ editableElement.focus();
+
+ /**
+ * Helper functions to set or get the value and the current selection of `editableElement`,
+ * regardless of its actual type.
+ */
+ const setValue = (aValue) => {
+ editableElement.tagName.toLowerCase() == "div"
+ ? editableElement.innerHTML = aValue
+ : editableElement.value = aValue;
+ }
+ const getValue = () => {
+ return editableElement.tagName.toLowerCase() == "div"
+ ? editableElement.innerHTML
+ : editableElement.value;
+ };
+ const getSelection = () => {
+ return editableElement.tagName.toLowerCase() == "div"
+ ? document.getSelection().toString()
+ : editableElement.value.substring(
+ editableElement.selectionStart,
+ editableElement.selectionEnd
+ );
+ };
+
+ /**
+ * Places a double click in `editableElement` at exactly the end of `aPlaceHolderText` and press delete.
+ * `aPlaceholderText` therefore should contain the same text as the value of the `editableElement`
+ * up to the point where the doubleclick should happen.
+ *
+ * If `aSelectionValue` is defined, the selection created by the double click is compared to `aSelectionValue`.
+ */
+ const doubleClickAndDelete = async (aPlaceHolderText, aSelectionValue = undefined) => {
+ placeHolder.innerHTML = aPlaceHolderText;
+ editableElement.focus();
+ await waitForRender();
+ const absInputPos = editableElement.getBoundingClientRect();
+ selectionOffset = {
+ x: placeHolder.getBoundingClientRect().width,
+ y: Math.floor(placeHolder.getBoundingClientRect().height / 2)
+ };
+ await (new test_driver.Actions()
+ // for some reason this still doesn't work:
+ // .pointerMove(Math.floor(selectionOffset.x), Math.floor(selectionOffset.y), { origin: editableElement })
+ // but this does:
+ .pointerMove(
+ Math.floor(absInputPos.x + selectionOffset.x),
+ Math.floor(absInputPos.y + selectionOffset.y),
+ { origin: "viewport" }
+ )
+ .pointerDown()
+ .pointerUp()
+ .pointerDown()
+ .pointerUp())
+ .send()
+ await waitForRender();
+ if (aSelectionValue !== undefined) {
+ assert_equals(getSelection(), aSelectionValue, "Wrong selection value!");
+ }
+ return test_driver.send_keys(editableElement, deleteKey);
+ };
+ if (editableElement.tagName.toLowerCase() == "div") {
+ promise_test(async t => {
+ setValue("<p>abc def<span></span></p>");
+ await doubleClickAndDelete("abc de", "def");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "<p>abc</p>",
+ "The <span> at the end of the string must be removed, as well as the whitespace in between words.");
+ }, `${editableElement.tagName}: An empty span at the end of the selection should be considered end of selection!`);
+ }
+ promise_test(async t => {
+ setValue("one two");
+ await doubleClickAndDelete("on", "one");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "two",
+ "The whitespace between words must be removed when a word at the beginning is selected and deleted!"
+ );
+ }, `${editableElement.tagName}: Remove word at the beginning of string should remove the whitespace in between.`);
+
+ promise_test(async t => {
+ setValue("one two");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one",
+ "The whitespace between words must be removed when a word is selected at the end of the string and deleted!"
+ );
+ }, `${editableElement.tagName}: Remove word at the end of a string should remove the whitespace in between.`);
+
+ promise_test(async t => {
+ setValue("one two three");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one three",
+ "One whitespace between words must be removed when a word is selected and deleted!"
+ );
+ await waitForRender();
+ if (editableElement.tagName.toLowerCase() == "div") {
+ document.getSelection().setBaseAndExtent(
+ editableElement.firstChild,
+ 0,
+ editableElement.firstChild,
+ 3
+ );
+ }
+ else {
+ editableElement.setSelectionRange(0, 3);
+ }
+ await test_driver.send_keys(editableElement, deleteKey);
+ // div[contenteditable] returns '&nbsp;three' here.
+ assert_equals(
+ getValue().replace(/&nbsp;/g, " "),
+ " three",
+ "The whitespace must not be removed when selecting a word without doubleclicking it!"
+ );
+
+ }, `${editableElement.tagName}: Remove word in the middle of a string should remove one whitespace ` +
+ "only if selection is created by double click.");
+
+ promise_test(async t => {
+ setValue("one two three");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one three",
+ "One whitespace between words must be removed when a word is selected and deleted!"
+ );
+ }, `${editableElement.tagName}: Only one whitespace character should be removed when there are multiple.`);
+
+ promise_test(async t => {
+ setValue("one two");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one ",
+ "One whitespace character between words must be removed when a word is selected and deleted!"
+ );
+ }, `${editableElement.tagName}: Only one whitespace character should be removed when ` +
+ "there are multiple whitespaces and the deleted range is the end of the string.");
+
+ promise_test(async t => {
+ setValue("one two, three");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one, three",
+ "The whitespace in front of the selected word must be removed when punctuation follows selection!"
+ );
+ }, `${editableElement.tagName}: Removing a word before punctuation should remove the whitespace.`);
+
+ promise_test(async t => {
+ setValue("one, two");
+ await doubleClickAndDelete("one, tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one,",
+ "The whitespace in front of the selected word must be removed!"
+ );
+ }, `${editableElement.tagName}: Remove a word after punctuation should remove the whitespace.`);
+
+ promise_test(async t => {
+ setValue("one\u00A0two, three"); // adds a &nbsp;
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one, three",
+ "The whitespace between words must be removed when a word is selected and deleted!"
+ );
+ }, `${editableElement.tagName}: Removing a word between a &nbsp; and punctuation should remove the nbsp character.`);
+
+ if (editableElement.tagName.toLowerCase() == "div") {
+ promise_test(async t => {
+ setValue("one two<br>");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one<br>",
+ "The line break must be preserved!"
+ );
+ }, `${editableElement.tagName}: Removing a word in front of a line break should preserve the line break.`);
+ }
+ if (editableElement.tagName.toLowerCase() == "textarea") {
+ promise_test(async t => {
+ setValue("one two\n");
+ await doubleClickAndDelete("one tw", "two");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "one\n",
+ "The line break must be preserved!"
+ );
+ }, `${editableElement.tagName}: RRemoving a word in front of a line break should preserve the line break.`);
+ }
+ promise_test(async t => {
+ setValue("one two");
+ await doubleClickAndDelete("on", "one");
+ await waitForRender();
+ assert_equals(
+ getValue(),
+ "two",
+ "The whitespace between words must be removed when a word at the beginning is selected and deleted!"
+ );
+ document.execCommand("undo", false, null);
+ assert_equals(
+ getValue(),
+ "one two",
+ "Undo action must restore the original state!"
+ );
+ document.execCommand("redo", false, null);
+ assert_equals(
+ getValue(),
+ "two",
+ "Redo action must remove the word and whitespace again!"
+ );
+ }, `${editableElement.tagName}: Undo and Redo actions should take the removed whitespace into account.`);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/editor/input-setRangeText-during-noframe-crash.html b/testing/web-platform/mozilla/tests/editor/input-setRangeText-during-noframe-crash.html
new file mode 100644
index 0000000000..815ec994e8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/editor/input-setRangeText-during-noframe-crash.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script>
+document.addEventListener("DOMContentLoaded", () => {
+ const input = document.querySelector("input");
+ input.select();
+ input.type = "text/x-ecmascript";
+ input.setRangeText("foo", 1, 1);
+ document.execCommand("enableObjectResizing");
+});
+</script>
+</head>
+<body>
+<input type="number" value="a">
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/editor/white-space-handling-in-mail-editor.html b/testing/web-platform/mozilla/tests/editor/white-space-handling-in-mail-editor.html
new file mode 100644
index 0000000000..06fe0acf6e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/editor/white-space-handling-in-mail-editor.html
@@ -0,0 +1,371 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<meta name="variant" content="?plaintext=true">
+<meta name="variant" content="?plaintext=false">
+<title>Testing white-space handling in mail editor mode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div contenteditable></div>
+<script>
+"use strict";
+
+const params = new URLSearchParams(location.search);
+const inPlaintextMode = params.get("plaintext") === "true";
+
+const editingHost = document.querySelector("div[contenteditable]");
+// To show white-spaces as-is, editing host should have "pre-wrap" style.
+// Then, editor does not need to convert white-spaces.
+editingHost.style.whiteSpace = "pre-wrap";
+
+const editor = SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
+editor.flags |= SpecialPowers.Ci.nsIEditor.eEditorMailMask;
+if (inPlaintextMode) {
+ editor.flags |= SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
+}
+
+test(() => {
+ editingHost.innerHTML = "<p><br></p>";
+ getSelection().collapse(editingHost.querySelector("p"), 0);
+ document.execCommand("insertText", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting first white-space into empty paragraph shouldn't convert the inserting white-space to an NBSP");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertText", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting second white-space next to a white-space shouldn't convert the inserting white-space nor the existing white-space to NBSP");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertText", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting 3rd white-space into middle of white-spaces shouldn't convert the inserting white-space nor the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("insertText", false, "a");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> a </p>",
+ "<p> a <br></p>",
+ ]
+ );
+}, "Inserting a character into middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> a </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 3);
+ document.execCommand("delete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Deleting a character at middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 3);
+ document.execCommand("delete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Deleting a white-space at middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> a </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("forwardDelete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Forward deleting a character at middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("forwardDelete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Forward deleting at middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p><br></p>";
+ getSelection().collapse(editingHost.querySelector("p"), 0);
+ document.execCommand("insertText", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;</p>",
+ "<p>&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting first NBSP into empty paragraph shouldn't convert the inserting NBSP to a white-space");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertText", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting second NBSP next to an NBSP shouldn't convert the inserting NBSP nor the existing NBSP to white-space");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertText", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting 3rd NBSP into middle of NBSPs shouldn't convert the inserting NBSP nor the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("insertText", false, "a");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;a&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;a&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting a character into middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0a\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 3);
+ document.execCommand("delete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Deleting a character at middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0\xA0\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 3);
+ document.execCommand("delete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Deleting an NBSP at middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0a\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("forwardDelete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Forward deleting a character at middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0\xA0\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("forwardDelete");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Forward deleting at middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p><br></p>";
+ getSelection().collapse(editingHost.querySelector("p"), 0);
+ document.execCommand("insertHTML", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting first white-space with insertHTML command into empty paragraph shouldn't convert the inserting white-space to an NBSP");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertHTML", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting second white-space with insertHTML command next to a white-space shouldn't convert the inserting white-space nor the existing white-space to NBSP");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertHTML", false, " ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> </p>",
+ "<p> <br></p>",
+ ]
+ );
+}, "Inserting 3rd white-space with insertHTML command into middle of white-spaces shouldn't convert the inserting white-space nor the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p> </p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("insertHTML", false, "a");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p> a </p>",
+ "<p> a <br></p>",
+ ]
+ );
+}, "Inserting a character with insertHTML command into middle of white-spaces shouldn't convert the existing white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p><br></p>";
+ getSelection().collapse(editingHost.querySelector("p"), 0);
+ document.execCommand("insertHTML", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;</p>",
+ "<p>&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting first NBSP with insertHTML command into empty paragraph shouldn't convert the inserting NBSP to a white-space");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertHTML", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting second NBSP with insertHTML command next to an NBSP shouldn't convert the inserting NBSP nor the existing NBSP to white-space");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 1);
+ document.execCommand("insertHTML", false, "\xA0");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting 3rd NBSP with insertHTML command into middle of NBSPs shouldn't convert the inserting NBSP nor the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>\xA0\xA0\xA0\xA0</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, 2);
+ document.execCommand("insertHTML", false, "a");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>&nbsp;&nbsp;a&nbsp;&nbsp;</p>",
+ "<p>&nbsp;&nbsp;a&nbsp;&nbsp;<br></p>",
+ ]
+ );
+}, "Inserting a character with insertHTML command into middle of NBSPs shouldn't convert the existing NBSPs to white-spaces");
+
+test(() => {
+ editingHost.innerHTML = "<p>abc</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, "abc".length);
+ document.execCommand("insertHTML", false, "def ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>abcdef </p>",
+ "<p>abcdef <br></p>",
+ ]
+ );
+}, "Inserting multiple white-spaces with insertHTML command shouldn't convert the white-spaces to NBSPs");
+
+test(() => {
+ editingHost.innerHTML = "<p>abc</p>";
+ getSelection().collapse(editingHost.querySelector("p").firstChild, "abc".length);
+ document.execCommand("insertHTML", false, "def ");
+ assert_in_array(
+ editingHost.innerHTML,
+ [
+ "<p>abcdef </p>",
+ "<p>abcdef <br></p>",
+ ]
+ );
+}, "Inserting multiple NBSPs with insertHTML command shouldn't convert the NBSPs to white-spaces");
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer-mixed-content.js b/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer-mixed-content.js
new file mode 100644
index 0000000000..ad59904fd9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer-mixed-content.js
@@ -0,0 +1,51 @@
+if (this.document === undefined) {
+ importScripts("/common/utils.js");
+ importScripts("/resources/testharness.js");
+ importScripts("/fetch/api/resources/utils.js");
+ importScripts("/common/get-host-info.sub.js");
+}
+
+function testReferrerAfterRedirection(desc, redirectUrl, redirectLocation, referrerPolicy, redirectReferrerPolicy, expectedReferrer) {
+ var url = redirectUrl;
+ var urlParameters = "?location=" + encodeURIComponent(redirectLocation);
+
+ if (redirectReferrerPolicy)
+ urlParameters += "&redirect_referrerpolicy=" + redirectReferrerPolicy;
+
+ var requestInit = {"redirect": "follow", "referrerPolicy": referrerPolicy};
+
+ promise_test(function(test) {
+ return fetch(url + urlParameters, requestInit).then(function(response) {
+ assert_equals(response.status, 200, "Inspect header response's status is 200");
+ assert_equals(response.headers.get("x-request-referer"), expectedReferrer ? expectedReferrer : null, "Check referrer header");
+ });
+ }, desc);
+}
+
+var referrerOrigin = get_host_info().HTTPS_ORIGIN + "/";
+var referrerUrl = location.href;
+
+var RESOURCES_DIR = "/fetch/api/resources/";
+var redirectUrl = RESOURCES_DIR + "redirect.py";
+var locationUrl = get_host_info().HTTPS_ORIGIN + RESOURCES_DIR + "inspect-headers.py?headers=referer";
+var httpLocationUrl = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR + "inspect-headers.py?cors&headers=referer";
+
+testReferrerAfterRedirection("Downgrade, empty init, unsafe-url redirect header ", redirectUrl, httpLocationUrl, "", "unsafe-url", referrerUrl);
+testReferrerAfterRedirection("Downgrade, empty init, no-referrer-when-downgrade redirect header ", redirectUrl, httpLocationUrl, "", "no-referrer-when-downgrade", null);
+testReferrerAfterRedirection("Downgrade, empty init, same-origin redirect header ", redirectUrl, httpLocationUrl, "", "same-origin", null);
+testReferrerAfterRedirection("Downgrade, empty init, origin redirect header ", redirectUrl, httpLocationUrl, "", "origin", referrerOrigin);
+testReferrerAfterRedirection("Downgrade, empty init, origin-when-cross-origin redirect header ", redirectUrl, httpLocationUrl, "", "origin-when-cross-origin", referrerOrigin);
+testReferrerAfterRedirection("Downgrade, empty init, no-referrer redirect header ", redirectUrl, httpLocationUrl, "", "no-referrer", null);
+testReferrerAfterRedirection("Downgrade, empty init, strict-origin redirect header ", redirectUrl, httpLocationUrl, "", "strict-origin", null);
+testReferrerAfterRedirection("Downgrade, empty init, strict-origin-when-cross-origin redirect header ", redirectUrl, httpLocationUrl, "", "strict-origin-when-cross-origin", null);
+
+testReferrerAfterRedirection("Downgrade, empty redirect header, unsafe-url init ", redirectUrl, httpLocationUrl, "unsafe-url", "", referrerUrl);
+testReferrerAfterRedirection("Downgrade, empty redirect header, no-referrer-when-downgrade init ", redirectUrl, httpLocationUrl, "no-referrer-when-downgrade", "", null);
+testReferrerAfterRedirection("Downgrade, empty redirect header, same-origin init ", redirectUrl, httpLocationUrl, "same-origin", "", null);
+testReferrerAfterRedirection("Downgrade, empty redirect header, origin init ", redirectUrl, httpLocationUrl, "origin", "", referrerOrigin);
+testReferrerAfterRedirection("Downgrade, empty redirect header, origin-when-cross-origin init ", redirectUrl, httpLocationUrl, "origin-when-cross-origin", "", referrerOrigin);
+testReferrerAfterRedirection("Downgrade, empty redirect header, no-referrer init ", redirectUrl, httpLocationUrl, "no-referrer", "", null);
+testReferrerAfterRedirection("Downgrade, empty redirect header, strict-origin init ", redirectUrl, httpLocationUrl, "strict-origin", "", null);
+testReferrerAfterRedirection("Downgrade, empty redirect header, strict-origin-when-cross-origin init ", redirectUrl, httpLocationUrl, "strict-origin-when-cross-origin", "", null);
+
+
diff --git a/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer.https.html b/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer.https.html
new file mode 100644
index 0000000000..bcd24892e2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/api/redirect/redirect-referrer.https.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Fetch: redirect referrer handling, mixed content</title>
+ <meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
+ <meta name="help" href="https://fetch.spec.whatwg.org/#main-fetch">
+ <meta name="help" href="https://fetch.spec.whatwg.org/#http-redirect-fetch">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script src="/common/utils.js"></script>
+ <script src="/fetch/api/resources/utils.js"></script>
+ <script src="/common/get-host-info.sub.js"></script>
+ <script src="redirect-referrer-mixed-content.js"></script>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/content-range.sub.window.js b/testing/web-platform/mozilla/tests/fetch/orb/tentative/content-range.sub.window.js
new file mode 100644
index 0000000000..e6fe872719
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/content-range.sub.window.js
@@ -0,0 +1,19 @@
+// META: script=/fetch/orb/resources/utils.js
+// META: script=resources/utils.js
+
+const url =
+ "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/orb/resources/image.png";
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ url,
+ { headers: new Headers([["Range", "bytes 10-99"]]) },
+ header("Content-Range", "bytes 10-99/1010"),
+ "slice(10,100)",
+ "status(206)"
+ ),
+ "ORB should filter opaque range of image/png not starting at zero, that isn't subsequent"
+);
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/img-mime-types-coverage.tentative.sub.html b/testing/web-platform/mozilla/tests/fetch/orb/tentative/img-mime-types-coverage.tentative.sub.html
new file mode 100644
index 0000000000..d5ab1a4cd7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/img-mime-types-coverage.tentative.sub.html
@@ -0,0 +1,43 @@
+<!-- Test verifies that cross-origin, nosniff images are 1) blocked when their
+ MIME type is covered by ORB and 2) allowed otherwise.
+
+ This test is very similar to fetch/orb/img-mime-types-coverage.tentative.sub.html,
+ except that it focuses on MIME types relevant to ORB.
+-->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ var passes = [
+ // These are exceptions that allow more MIME types than the ORB spec does.
+ // This is due to web compat, but might be removed in the future.
+ // See Bug 1828375
+ "application/dash+xml",
+ "application/vnd.apple.mpegurl",
+ "audio/mpegurl",
+ "audio/mpeg",
+ "text/vtt",
+ ]
+
+ const get_url = (mime) => {
+ // www1 is cross-origin, so the HTTP response is ORB-eligible -->
+ url = "http://{{domains[www1]}}:{{ports[http][0]}}"
+ url = url + "/fetch/nosniff/resources/image.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ return url
+ }
+
+ passes.forEach(function (mime) {
+ async_test(function (t) {
+ var img = document.createElement("img")
+ img.onerror = t.unreached_func("Unexpected error event")
+ img.onload = t.step_func_done(function () {
+ assert_equals(img.width, 96)
+ })
+ img.src = get_url(mime)
+ document.body.appendChild(img)
+ }, "ORB should allow the response if Content-Type is: '" + mime + "'. ")
+ })
+</script>
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/known-mime-type.sub.window.js b/testing/web-platform/mozilla/tests/fetch/orb/tentative/known-mime-type.sub.window.js
new file mode 100644
index 0000000000..1779b8ddfc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/known-mime-type.sub.window.js
@@ -0,0 +1,48 @@
+// META: script=/fetch/orb/resources/utils.js
+// META: script=resources/utils.js
+
+const path = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/orb/resources";
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(`${path}/font.ttf`, null, contentType("font/ttf")),
+ "ORB should filter opaque font/ttf"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(`${path}/text.txt`, null, contentType("text/plain")),
+ "ORB should filter opaque text/plain"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(`${path}/data.json`, null, contentType("application/json")),
+ "ORB should filter opaque application/json (non-empty)"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(`${path}/empty.json`, null, contentType("application/json")),
+ "ORB should filter opaque application/json (empty)"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ `${path}/data_non_ascii.json`,
+ null,
+ contentType("application/json")
+ ),
+ "ORB should filter opaque application/json which contains non ascii characters"
+);
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/nosniff.sub.window.js b/testing/web-platform/mozilla/tests/fetch/orb/tentative/nosniff.sub.window.js
new file mode 100644
index 0000000000..7468921b30
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/nosniff.sub.window.js
@@ -0,0 +1,44 @@
+// META: script=/fetch/orb/resources/utils.js
+// META: script=resources/utils.js
+
+const path = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/orb/resources";
+
+// This is an exception that allow more MIME types than the ORB spec does.
+// This is due to web compatibility, but might be removed in the future.
+// See Bug 1828375
+promise_test(
+ async () =>
+ await fetchORB(
+ `${path}/text.txt`,
+ null,
+ contentType("text/plain"),
+ contentTypeOptions("nosniff")
+ ),
+ "ORB shouldn't block opaque text/plain with nosniff"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ `${path}/data.json`,
+ null,
+ contentType("application/json"),
+ contentTypeOptions("nosniff")
+ ),
+ "ORB should filter opaque-response-blocklisted MIME type with nosniff"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ `${path}/data.json`,
+ null,
+ contentType(""),
+ contentTypeOptions("nosniff")
+ ),
+ "ORB should filter opaque response with empty Content-Type and nosniff"
+);
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/resources/utils.js b/testing/web-platform/mozilla/tests/fetch/orb/tentative/resources/utils.js
new file mode 100644
index 0000000000..b4f63b4416
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/resources/utils.js
@@ -0,0 +1,21 @@
+function promise_internal_response_is_filtered(fetchPromise, message) {
+ return promise_test(async () => {
+ const response = await fetchPromise;
+
+ // A parent filtered opaque response is defined here as a response that isn't just an
+ // opaque response, but also where the internal response has been made unavailable.
+ // `Response.cloneUnfiltered` is used to inspect the state of the internal response,
+ // which is exactly what we want to be missing in this case.
+ const unfiltered = SpecialPowers.wrap(response).cloneUnfiltered();
+ assert_equals(
+ await SpecialPowers.unwrap(unfiltered).text(),
+ "",
+ "The internal response should be empty"
+ );
+ assert_equals(
+ Array.from(await SpecialPowers.unwrap(unfiltered).headers).length,
+ 0,
+ "The internal response should have no headers"
+ );
+ }, message);
+}
diff --git a/testing/web-platform/mozilla/tests/fetch/orb/tentative/status.sub.window.js b/testing/web-platform/mozilla/tests/fetch/orb/tentative/status.sub.window.js
new file mode 100644
index 0000000000..902759b63a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/fetch/orb/tentative/status.sub.window.js
@@ -0,0 +1,30 @@
+// META: script=/fetch/orb/resources/utils.js
+// META: script=resources/utils.js
+
+const path = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/orb/resources";
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ `${path}/data.json`,
+ null,
+ contentType("application/json"),
+ "status(206)"
+ ),
+ "ORB should filter opaque-response-blocklisted MIME type with status 206"
+);
+
+// Due to web compatibility we filter opaque Response object from the
+// fetch() function in the Fetch specification. See Bug 1823877. This
+// might be removed in the future.
+promise_internal_response_is_filtered(
+ fetchORB(
+ `${path}/data.json`,
+ null,
+ contentType("application/json"),
+ "status(302)"
+ ),
+ "ORB should filter opaque range of image/png not starting at zero, that isn't subsequent"
+);
diff --git a/testing/web-platform/mozilla/tests/focus/Range_collapse.html b/testing/web-platform/mozilla/tests/focus/Range_collapse.html
new file mode 100644
index 0000000000..7c16f16bec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_collapse.html
@@ -0,0 +1,207 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.collapse()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(true) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(false) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(false) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'anchor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(false) of selection between start of the first text node of 'editor' and end of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(true) of selection between start of the first text node of 'editor' and end of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(false) of selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(true) of selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Range.collapse(false) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Range.collapse(true) of selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' when active element is 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.collapse(true) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(false) of selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.collapse(true) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(false) of selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(true) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(true);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.collapse(true) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().getRangeAt(0).collapse(false);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.collapse(false) of selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' when active element is 'outerEditor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_selectNode.html b/testing/web-platform/mozilla/tests/focus/Range_selectNode.html
new file mode 100644
index 0000000000..3975653d2c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_selectNode.html
@@ -0,0 +1,267 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.selectNode() and Range.selectNodeContents()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function selectNode(aNodeToSelect)
+{
+ document.getSelection().getRangeAt(0).selectNode(aNodeToSelect);
+}
+
+function selectNodeContents(aNodeToSelectItsContents)
+{
+ document.getSelection().getRangeAt(0).selectNodeContents(aNodeToSelectItsContents);
+}
+
+[{ func: selectNode, doingDescription: "Range.selectNode()" },
+ { func: selectNodeContents, doingDescription: "Range.selectNodeContents()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the <body>");
+
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'editor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'outerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(staticBefore.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'staticBefore' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with the first text node of 'editor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with the first text node of 'outerEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(staticInEditor.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'staticInEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with the first text node of 'innerEditor' when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ aTest.func(anchor.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with the first text node of 'anchor' when active element is the 'anchor'");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_setEnd.html b/testing/web-platform/mozilla/tests/focus/Range_setEnd.html
new file mode 100644
index 0000000000..e1eed4ae71
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_setEnd.html
@@ -0,0 +1,364 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.setEnd(), Range.setEndAfter() and Range.setEndBefore()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function setEnd(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEnd(aNode, aOffset);
+}
+
+function setEndBefore(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEndBefore(aNode);
+}
+
+function setEndAfter(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setEndAfter(aNode);
+}
+
+// Range.setEnd*() should work same as collapse if specified end position is before its start.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.textNode);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the selection) when active element is 'anchor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, staticBefore.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().collapse(anchor.textNode, anchor.textLength);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'anchor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(anchor.textNode, anchor.textLength);
+ aTest.func(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (before the collapsed selection) when active element is the <body>");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, staticBefore.textLength,
+ editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection, between end of the first text node of 'staticBefore' and end of the first text node of 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, editor.textLength,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection, between end of the first text node of 'editor' and end of the first text node of 'outerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, outerEditor.textLength,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection, between end of the first text node of 'outerEditor' and end of the first text node of 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, staticInEditor.textLength,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (before the selection, between end of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor') when active element is the <body>");
+});
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticAfter.textNode);
+ setEndAfter(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setEndAfter(staticInEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ setEndAfter(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setEndAfter(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ setEndAfter(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ setEndAfter(staticBefore.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.textNode);
+ setEndAfter(staticBefore.textNode);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'anchor'");
+
+// Range.setEnd*() should blur focused editing host when it expands selection to outside of it.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndAfter, doingDescription: "Range.setEndAfter()" },
+ { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, 0);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor'");
+});
+
+// Range.setEnd*() should move focus to an editing host when the range is shrunken into it.
+[{ func: setEnd, doingDescription: "Range.setEnd()" },
+ { func: setEndAfter, doingDescription: "Range.setEndAfter()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'innerEditor' and selection end is in 'staticAfter'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is the <body>");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Range_setStart.html b/testing/web-platform/mozilla/tests/focus/Range_setStart.html
new file mode 100644
index 0000000000..9297aa02ab
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Range_setStart.html
@@ -0,0 +1,353 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Range.setStart(), Range.setStartAfter() and Range.setStartBefore()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+function setStart(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStart(aNode, aOffset);
+}
+
+function setStartBefore(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStartBefore(aNode);
+}
+
+function setStartAfter(aNode, aOffset)
+{
+ document.getSelection().getRangeAt(0).setStartAfter(aNode);
+}
+
+// Range.setStart*() should work same as collapse if specified start position is after its end.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartAfter, doingDescription: "Range.setStartAfter()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.textNode);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.textNode);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, 0);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, 0);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection, between start of the first text node of 'staticBefore' and start of the first text node of 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, 0);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection, between start of the first text node of 'editor' and start of the first text node of 'outerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'staticInEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ aTest.func(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'staticInEditor' and start of the first text node of 'innerEditor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, 0);
+ aTest.func(staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection, between start of the first text node of 'innerEditor' and start of the first text node of 'staticAfter') when active element is the <body>");
+});
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.textNode);
+ setStartBefore(editor.textNode);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Range.setStartBefore() with the first text node of 'editor' (before the selection) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ setStartBefore(outerEditor.textNode);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Range.setStartBefore() with the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ setStartBefore(innerEditor.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ setStartBefore(staticAfter.textNode);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticAfter.textNode);
+ setStartBefore(anchor.textNode);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Range.setStartBefore() with the first text node of 'anchor' (before the selection) when active element is the <body>");
+
+// Range.setStart*() should blur focused editing host when it expands selection to outside of it.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartAfter, doingDescription: "Range.setStartAfter()" },
+ { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().collapse(editor.textNode, editor.textLength);
+ aTest.func(staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor'");
+
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.textNode);
+ aTest.func(staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.textNode);
+ aTest.func(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.textNode);
+ aTest.func(staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
+});
+
+// Range.setStart*() should move focus to an editing host when the range is shrunken into it.
+[{ func: setStart, doingDescription: "Range.setStart()" },
+ { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ aTest.func(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
+ test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ aTest.func(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'editor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ aTest.func(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ aTest.func(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'outerEditor'");
+ test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ aTest.func(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (shrunken into 'anchor') when active element is the <body>");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange.html
new file mode 100644
index 0000000000..d94e688158
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange.html
@@ -0,0 +1,1242 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+/**
+ * NOTE: When you add/modify something in this file, you should add same test to Selection_setBaseAndExtent.html too.
+ */
+
+
+// Selection.addRange() with collapsed range.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is the <body> and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with collapsed range at start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with collapsed range at start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.addRange() with non-collapsed range in a node.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(staticBefore.textNode, staticBefore.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range in start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range in start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range in start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticAfter.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(anchor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range in start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.addRange() with a range across editing host boundary.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticBefore.textNode, 0);
+ range.setEnd(editor.textNode, editor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(editor.textNode, 0);
+ range.setEnd(outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(staticInEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(outerEditor.textNode, 0);
+ range.setEnd(innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.addRange() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ var range = document.createRange();
+ range.setStart(innerEditor.textNode, 0);
+ range.setEnd(anchor.textNode, anchor.textLength);
+ document.getSelection().addRange(range);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.addRange() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html
new file mode 100644
index 0000000000..71b7c26c46
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_in_iframe.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move and auto scroll tests caused by a call of Selection.addRange() into a contenteditable element in iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<iframe srcdoc="<div style='height: 1000px;'></div><div id='editor' contenteditable>editor</div>" style="height: 500px;"></iframe>
+<script>
+"use strict";
+setup({explicit_done:true});
+
+window.onload = ()=>{
+ test(function() {
+ var subDocument = document.querySelector("iframe").contentDocument;
+ var editorInFrame = subDocument.getElementById("editor");
+ var range = subDocument.createRange();
+ range.setStart(editorInFrame, 0);
+ var selection = subDocument.getSelection();
+ selection.removeAllRanges();
+ document.documentElement.scrollTop = 0;
+ subDocument.documentElement.scrollTop = 0;
+ selection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(subDocument.activeElement, editorInFrame);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+ }, "Moving selection into inactive contenteditable element in non-focused document shouldn't cause scrolling");
+
+ test(function() {
+ var iframe = document.querySelector("iframe");
+ var subDocument = iframe.contentDocument;
+ var selection = subDocument.getSelection();
+
+ // Reset selection in <iframe>
+ var editorInFrame = subDocument.getElementById("editor");
+ editorInFrame.blur();
+ selection.removeAllRanges();
+ var range = document.createRange();
+ range.setStart(subDocument.body, 0);
+ selection.addRange(range);
+ subDocument.documentElement.scrollTop = 0;
+
+ // Move focus to the <iframe>
+ iframe.contentWindow.focus();
+ document.documentElement.scrollTop = 0;
+ assert_equals(document.activeElement, iframe);
+ assert_equals(subDocument.activeElement, subDocument.body);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+
+ range = subDocument.createRange();
+ range.setStart(editorInFrame, 0);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ assert_equals(document.activeElement, iframe);
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(subDocument.activeElement, editorInFrame);
+ assert_equals(subDocument.documentElement.scrollTop, 0);
+ }, "Moving selection into inactive contenteditable element in focused document shouldn't cause scrolling");
+
+ done();
+};
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html
new file mode 100644
index 0000000000..e06e9cd17a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange() into iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body onload="doTest()">
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p>Here is an iframe:</p>
+<iframe src="Selection_addRange_into_iframe_iframe.html"></iframe>
+<script>
+"use strict";
+
+setup({explicit_done:true});
+
+function doTest() {
+ var selection = document.getSelection();
+ var childDocument = document.getElementsByTagName("iframe")[0].contentDocument;
+ var childSelection = childDocument.getSelection();
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.body.firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("editor1"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor1"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor1' in the <iframe> after Selection.addRange() but parent's active document should be the <body>");
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.getElementById("editor1").firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("editor2"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor2"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor2' in the <iframe> after Selection.addRange() but parent's active document should be the <body>");
+ test(function() {
+ selection.collapse(document.body.firstChild, 0);
+ childSelection.collapse(childDocument.getElementById("editor2").firstChild, 0);
+
+ document.documentElement.scrollTop = 0;
+ childDocument.documentElement.scrollTop = 0;
+ childSelection.removeAllRanges();
+ var range = childDocument.createRange();
+ range.selectNodeContents(childDocument.getElementById("non-editor"));
+ childSelection.addRange(range);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(childDocument.activeElement, childDocument.getElementById("editor2"));
+ assert_equals(document.documentElement.scrollTop, 0);
+ assert_equals(childDocument.documentElement.scrollTop, 0);
+ }, "Active element should be 'editor2' in the <iframe> after Selection.addRange() to non-editable <div> and parent's active document should be the <body>");
+
+ done();
+}
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html
new file mode 100644
index 0000000000..946d4aa5e7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_addRange_into_iframe_iframe.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=utf-8>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p>Here are two editors:</p>
+<div id="editor1" contenteditable>The first editor.</div>
+<div id="editor2" contenteditable>The second editor.</div>
+<div id="non-editor">The non-editable div.</div>
+</body>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapse.html b/testing/web-platform/mozilla/tests/focus/Selection_collapse.html
new file mode 100644
index 0000000000..2e3050d822
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapse.html
@@ -0,0 +1,148 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapse()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() not moving selection from first text node in the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().collapse(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapse() moving selection from first text node in the <body> to start of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in 'outerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of the <body>");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().collapse(anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapse() moving selection from first text node in 'innerEditor' to start of the first text node of 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html b/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html
new file mode 100644
index 0000000000..f768782650
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapseToEnd.html
@@ -0,0 +1,134 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapseToEnd()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToEnd() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToEnd() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToEnd() with selection between start of the first text node of 'editor' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.collapseToEnd() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToEnd() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToEnd();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToEnd() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html b/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html
new file mode 100644
index 0000000000..238a436c1b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_collapseToStart.html
@@ -0,0 +1,142 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.collapseToStart()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToStart() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.collapseToStart() with selection between start of the first text node of 'editor' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.collapseToStart() with selection between start of the first text node of 'anchor' and end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.collapseToStart() with selection between start of the first text node of 'staticBefore' and end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'editor' and end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ document.getSelection().collapseToStart();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.collapseToStart() with selection between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_extend.html b/testing/web-platform/mozilla/tests/focus/Selection_extend.html
new file mode 100644
index 0000000000..62136cc4a3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_extend.html
@@ -0,0 +1,189 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.extend()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(editor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().extend(anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'staticBefore' to start of the first text node of 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to end of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.extend() from selection at start of the first text node of 'editor' to start of the first text node of 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to end of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(innerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().extend(editor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'outerEditor' to start of the first text node of 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to end of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().extend(anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.extend() from selection at start of the first text node of 'innerEditor' to start of the first text node of 'anchor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().extend(anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.extend() from selection at start of the first text node of 'anchor' to end of the first text node of 'anchor' and 'anchor' has focus before the call");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ anchor.element.blur();
+ document.getSelection().extend(anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.extend() from selection at start of the first text node of 'anchor' to end of the first text node of 'anchor' and 'anchor' doesn't have focus before the call");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html b/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html
new file mode 100644
index 0000000000..6e6854d44b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_removeAllRanges.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.removeAllRanges()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange(staticBefore);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticBefore'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.removeAllRanges() when active element is 'editor' and selection is at the start of the first text node of 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.removeAllRanges() when active element is 'outerEditor' and selection is at the start of the first text node of 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.removeAllRanges() when active element is 'innerEditor' and selection is at the start of the first text node of 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticAfter);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeAllRanges() when active element is the <body> and selection is at the start of the first text node of 'staticAfter'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeAllRanges();
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.removeAllRanges() when active element is 'anchor' and selection is at the start of the first text node of 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html b/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html
new file mode 100644
index 0000000000..14e78381d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_removeRange.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.removeRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange(staticBefore);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.removeRange() to remove selected range at the start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.removeRange() to remove selected range at the start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.removeRange() to remove selected range at the start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticAfter);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.removeRange() to remove selected range at the start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().removeRange(document.getSelection().getRangeAt(0));
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.removeRange() to remove selected range at the start of the first text node of 'anchor' when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html b/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html
new file mode 100644
index 0000000000..2753e60851
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_selectAllChildren.html
@@ -0,0 +1,254 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.selectAllChildren()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.selectAllChildren() to select the children of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'ouerEditor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(staticBefore.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(editor.element);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.selectAllChildren() to select the children of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(outerEditor.element);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.selectAllChildren() to select the children of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(staticInEditor.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(innerEditor.element);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.selectAllChildren() to select the children of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().selectAllChildren(anchor.element);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.selectAllChildren() to select the children of 'anchor' when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html b/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html
new file mode 100644
index 0000000000..7cfc110009
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/Selection_setBaseAndExtent.html
@@ -0,0 +1,926 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.setBaseAndExtent()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
+<p id="staticBefore">static text</p>
+<div id="editor" contenteditable><p>content of editor</p></div>
+<div id="outerEditor" contenteditable
+><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
+><p>static content of outer editor</p><div id="innerEditor" contenteditable
+><p>content of inner editor</p></div></div></div>
+<p id="staticAfter">static text</p>
+<p><a id="anchor" href="about:blank">anchor</a></p>
+<script>
+"use strict";
+
+var staticBefore = {
+ element: document.getElementById("staticBefore"),
+ textNode: document.getElementById("staticBefore").firstChild,
+ textLength: document.getElementById("staticBefore").firstChild.length
+};
+var editor = {
+ element: document.getElementById("editor"),
+ textNode: document.getElementById("editor").firstChild.firstChild,
+ textLength: document.getElementById("editor").firstChild.firstChild.length
+};
+var outerEditor = {
+ element: document.getElementById("outerEditor"),
+ textNode: document.getElementById("outerEditor").firstChild.firstChild,
+ textLength: document.getElementById("outerEditor").firstChild.firstChild.length
+};
+var staticInEditor = {
+ element: document.getElementById("staticInEditor"),
+ textNode: document.getElementById("staticInEditor").firstChild,
+ textLength: document.getElementById("staticInEditor").firstChild.length
+};
+var innerEditor = {
+ element: document.getElementById("innerEditor"),
+ textNode: document.getElementById("innerEditor").firstChild.firstChild,
+ textLength: document.getElementById("innerEditor").firstChild.firstChild.length
+};
+var staticAfter = {
+ element: document.getElementById("staticAfter"),
+ textNode: document.getElementById("staticAfter").firstChild,
+ textLength: document.getElementById("staticAfter").firstChild.length
+};
+var anchor = {
+ element: document.getElementById("anchor"),
+ textNode: document.getElementById("anchor").firstChild,
+ textLength: document.getElementById("anchor").firstChild.length
+};
+
+function resetFocusAndSelectionRange(aFocus)
+{
+ document.getSelection().removeAllRanges();
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ if (aFocus) {
+ aFocus.element.focus();
+ document.getSelection().collapse(aFocus.textNode, 0);
+ } else {
+ document.getSelection().collapse(staticBefore.textNode, 0);
+ }
+ document.documentElement.scrollTop = 0;
+}
+
+/**
+ * NOTE: When you add/modify something in this file, you should add same test to Selection_addRange.html too.
+ */
+
+// Selection.setBaseAndExtent() with collapsed range.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is the <body> and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is the <body> and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, 0);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, 0);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, 0);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, 0);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with collapsed range at start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.setBaseAndExtent() with non-collapsed range in a node.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+test(function() {
+ resetFocusAndSelectionRange(staticInEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'outerEditor' and selection is in 'staticInEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ staticBefore.textNode, staticBefore.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in the first text node of 'staticBefore' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'editor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'outerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticInEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range in start of the first text node of 'innerEditor' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticAfter.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'staticAfter' when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(anchor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range in start of the first text node of 'anchor' when active element is 'anchor'");
+
+// Selection.setBaseAndExtent() with a range across editing host boundary.
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is the <body>");
+test(function() {
+ resetFocusAndSelectionRange();
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, document.body);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be the <body> after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is the <body>");
+
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'editor'");
+test(function() {
+ resetFocusAndSelectionRange(editor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, editor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'editor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'editor'");
+
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'outerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(outerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'outerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'innerEditor'");
+test(function() {
+ resetFocusAndSelectionRange(innerEditor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, innerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'innerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'innerEditor'");
+
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
+ editor.textNode, editor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticBefore' and end of the first text node of 'editor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(editor.textNode, 0,
+ outerEditor.textNode, outerEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'editor' and end of the first text node of 'outerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ staticInEditor.textNode, staticInEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'staticInEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
+ innerEditor.textNode, innerEditor.textLength);
+ assert_equals(document.activeElement, outerEditor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'outerEditor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'outerEditor' and end of the first text node of 'innerEditor' (common editing host is outerEditor) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ staticAfter.textNode, staticAfter.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'staticAfter' (no common editing host) when active element is 'anchor'");
+test(function() {
+ resetFocusAndSelectionRange(anchor);
+ document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
+ anchor.textNode, anchor.textLength);
+ assert_equals(document.activeElement, anchor.element);
+ assert_equals(document.documentElement.scrollTop, 0);
+}, "Active element should be 'anchor' after Selection.setBaseAndExtent() with a range between start of the first text node of 'innerEditor' and end of the first text node of 'anchor' (no common editing host) when active element is 'anchor'");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html b/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html
new file mode 100644
index 0000000000..35fd30f1f6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/delegateFocus-is-focusable.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus move tests caused by a call of Selection.addRange()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="host"></div>
+<script>
+let host = document.getElementById("host");
+let shadow = host.attachShadow({ mode: "open", delegatesFocus: true });
+shadow.innerHTML = `<button>Focusable</button>`;
+
+test(function() {
+ assert_true(SpecialPowers.Services.focus.elementIsFocusable(host, 0), "host is focusable");
+ host.focus();
+ assert_equals(document.activeElement, host, "Host is focused");
+ assert_equals(shadow.activeElement, shadow.querySelector("button"), "Button is focused");
+ assert_true(SpecialPowers.Services.focus.elementIsFocusable(host, 0), "host is still focusable");
+}, "isElementFocusable with delegateFocus");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html
new file mode 100644
index 0000000000..e765990145
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-different-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() before iframe loaded different site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-before-iframe-loaded-different-site-outer.sub.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html
new file mode 100644
index 0000000000..fd7c2bffa6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-before-iframe-loaded-same-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() before iframe loaded same site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-before-iframe-loaded-same-site-outer.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html
new file mode 100644
index 0000000000..58310fd687
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-different-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() from next tick before iframe loaded different site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html
new file mode 100644
index 0000000000..01b467718c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/focus-next-tick-before-iframe-loaded-same-site.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>focus() from next tick before iframe loaded same site</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+setup({explicit_done:true});
+window.onmessage = function(e) {
+ test(function() {
+ assert_equals(e.data, "PASS", "Check verdict");
+ }, "Check result");
+ w.close();
+ done();
+};
+var w = window.open("support/focus-next-tick-before-iframe-loaded-same-site-outer.html");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html b/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html
new file mode 100644
index 0000000000..82a1346ec6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/iframe-focus-event-after-iframe-gets-focus.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test focus event after iframe gets focus</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+function waitForMessage(target, checkFn) {
+ return new Promise(resolve => {
+ target.addEventListener("message", e => {
+ if (checkFn && !checkFn(e)) {
+ return;
+ }
+ resolve();
+ }, { once: true });
+ });
+}
+
+function start(w) {
+ w.postMessage("start", "*");
+}
+
+// This will send message to outer frame and also inner frame to ask them
+// send the log they collect back, the logs of outer and inner will be
+// concatenated.
+async function getLog(w) {
+ let log = "";
+ step_timeout(function() {
+ w.postMessage("getlog", "*");
+ }, 0);
+ await waitForMessage(window, (e) => {
+ log = e.data;
+ return true;
+ });
+ return log;
+}
+
+function runSingleTest(url, focusIframeFunction, expectedResult, description) {
+ promise_test(async t => {
+ let w = window.open(url);
+ t.add_cleanup(() => { w.close(); });
+ await waitForMessage(window, e => e.data === "ready");
+ start(w);
+ focusIframeFunction(w);
+ assert_equals(await getLog(w), expectedResult);
+ }, description);
+}
+
+function runTests(url, description) {
+ // Test calling iframe.focus();
+ runSingleTest(url, (w) => {
+ w.postMessage("iframefocus", "*");
+ }, "outerlog:windowblur,innerlog:windowfocus,",
+ description + " via calling iframe.focus()");
+
+ // Test calling iframe.contentWindow.focus();
+ runSingleTest(url, (w) => {
+ w.postMessage("iframecontentWindowfocus", "*");
+ }, "outerlog:windowblur,innerlog:windowfocus,",
+ description + " via calling iframe.contentWindow.focus()");
+
+ // Test calling window.focus() in iframe;
+ runSingleTest(url, (w) => {
+ w.postMessage("windowfocus", "*");
+ }, "outerlog:windowblur,innerlog:willfocuswindow,windowfocus,didfocuswindow,",
+ description + " via calling window.focus() in iframe");
+}
+
+// Test same site iframe
+runTests("support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html",
+ "Check iframe focus event after same site iframe gets focus");
+
+// Test different site iframe
+runTests("support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html",
+ "Check iframe focus event after different site iframe gets focus");
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html
new file mode 100644
index 0000000000..bcf23627d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() before iframe loaded different site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html
new file mode 100644
index 0000000000..e95fe7d292
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-different-site-outer.sub.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() before iframe loaded different site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/focus-before-iframe-loaded-different-site-inner.html";
+document.body.appendChild(iframe);
+iframe.focus();
+if (document.activeElement != iframe) {
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html
new file mode 100644
index 0000000000..3c277f078f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() before iframe loaded same site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html
new file mode 100644
index 0000000000..8c829d6d47
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-before-iframe-loaded-same-site-outer.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() before iframe loaded same site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "focus-before-iframe-loaded-same-site-inner.html";
+document.body.appendChild(iframe);
+iframe.focus();
+if (document.activeElement != iframe) {
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html
new file mode 100644
index 0000000000..2c1b35f2b2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() from next tick before iframe loaded different site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html
new file mode 100644
index 0000000000..83a48e303d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-different-site-outer.sub.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() from next tick before iframe loaded different site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "tick") {
+ iframe.focus();
+ if (document.activeElement != iframe) {
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+ }
+ return;
+ }
+
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/focus-next-tick-before-iframe-loaded-different-site-inner.html";
+document.body.appendChild(iframe);
+window.postMessage("tick", "*");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html
new file mode 100644
index 0000000000..62add75ed9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>focus() from next tick before iframe loaded same site</title>
+</head>
+<body>
+<script>
+ window.onload = function() {
+ parent.postMessage("onload", "*");
+ }
+ document.body.onfocus = function() {
+ parent.postMessage("onfocus", "*");
+ }
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html
new file mode 100644
index 0000000000..a68d34039d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/focus-next-tick-before-iframe-loaded-same-site-outer.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>focus() from next tick before iframe loaded same site</title>
+</head>
+<body>
+<script>
+var pendingTimeout = false;
+window.onmessage = function(e) {
+ if (e.data == "tick") {
+ iframe.focus();
+ if (document.activeElement != iframe) {
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ opener.postMessage("FAIL activeElement", "*");
+ }
+ return;
+ }
+
+ if (e.data == "onload") {
+ if (pendingTimeout) {
+ return;
+ }
+ pendingTimeout = opener.step_timeout(function() {
+ opener.postMessage("FAIL missing onfocus", "*");
+ }, 2000);
+ return;
+ }
+ if (pendingTimeout) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = true;
+ if (e.data == "onfocus") {
+ // Test not upstreamed, because this even is a Firefoxism
+ // https://github.com/whatwg/html/issues/6209
+ opener.postMessage("PASS", "*");
+ return;
+ }
+ opener.postMessage("FAIL " + e.data, "*");
+}
+
+var iframe = document.createElement("iframe");
+iframe.src = "focus-next-tick-before-iframe-loaded-same-site-inner.html";
+document.body.appendChild(iframe);
+window.postMessage("tick", "*");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html
new file mode 100644
index 0000000000..d69580237c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-different-site-iframe-gets-focus-outer.sub.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Iframe focus event after different site iframe gets focus outer</title>
+<iframe src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/_mozilla/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html"></iframe>
+<script>
+let outerlog = "outerlog:";
+
+let iframe = document.querySelector("iframe");
+window.onmessage = function(e) {
+ if (e.data == "start") {
+ window.onfocus = function() {
+ outerlog += "windowfocus,";
+ };
+ } else if (e.data == "iframefocus") {
+ iframe.focus();
+ } else if (e.data == "iframecontentWindowfocus") {
+ iframe.contentWindow.focus();
+ } else if (e.data == "windowfocus") {
+ iframe.contentWindow.postMessage("windowfocus", "*");
+ } else if (e.data == "getlog") {
+ iframe.contentWindow.postMessage("getlog", "*");
+ } else {
+ opener.postMessage(outerlog + e.data, "*");
+ }
+};
+
+window.onload = function() {
+ window.onblur = function() {
+ outerlog += "windowblur,";
+ };
+
+ iframe.onfocus = function() {
+ outerlog += "iframefocus,";
+ };
+
+ iframe.onblur = function() {
+ outerlog += "iframeblur,";
+ };
+
+ opener.postMessage("ready", "*");
+};
+</script>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html
new file mode 100644
index 0000000000..64a360d248
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-iframe-gets-focus-inner.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Iframe focus event inner document</title>
+</head>
+<body>
+<h1>Inner</h1>
+<script>
+let innerlog = "innerlog:";
+
+window.onmessage = function(e) {
+ if (e.data == "windowfocus") {
+ innerlog += "willfocuswindow,";
+ window.focus();
+ innerlog += "didfocuswindow,";
+ } else if (e.data == "getlog") {
+ parent.postMessage(innerlog, "*");
+ }
+};
+
+window.onfocus = function() {
+ innerlog += "windowfocus,";
+};
+
+window.onblur = function() {
+ innerlog += "windowblur,";
+};
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html
new file mode 100644
index 0000000000..06040d6485
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/focus/support/iframe-focus-event-after-same-site-iframe-gets-focus-outer.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Iframe focus event after same site iframe gets focus outer</title>
+<iframe src="iframe-focus-event-after-iframe-gets-focus-inner.html"></iframe>
+<script>
+let outerlog = "outerlog:";
+
+let iframe = document.querySelector("iframe");
+window.onmessage = function(e) {
+ if (e.data == "start") {
+ window.onfocus = function() {
+ outerlog += "windowfocus,";
+ };
+ } else if (e.data == "iframefocus") {
+ iframe.focus();
+ } else if (e.data == "iframecontentWindowfocus") {
+ iframe.contentWindow.focus();
+ } else if (e.data == "windowfocus") {
+ iframe.contentWindow.postMessage("windowfocus", "*");
+ } else if (e.data == "getlog") {
+ iframe.contentWindow.postMessage("getlog", "*");
+ } else {
+ opener.postMessage(outerlog + e.data, "*");
+ }
+};
+
+window.onload = function() {
+ window.onblur = function() {
+ outerlog += "windowblur,";
+ };
+
+ iframe.onfocus = function() {
+ outerlog += "iframefocus,";
+ };
+
+ iframe.onblur = function() {
+ outerlog += "iframeblur,";
+ };
+
+ opener.postMessage("ready", "*");
+};
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/browsers/browsing-the-web/read-media/sandboxed-video.html b/testing/web-platform/mozilla/tests/html/browsers/browsing-the-web/read-media/sandboxed-video.html
new file mode 100644
index 0000000000..4c58514e66
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/browsers/browsing-the-web/read-media/sandboxed-video.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Test load of media document in sandboxed iframe</title>
+<link rel="motivation" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1783601">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body></body>
+<script>
+promise_test(async () => {
+ const frame = document.createElement('iframe');
+ frame.sandbox = '';
+ frame.src =
+ // 'PartialContent' ensures that the entire video resource does not load
+ // in one fetch.
+ '/service-workers/service-worker/resources/fetch-access-control.py?'
+ + 'VIDEO&PartialContent';
+
+ document.body.appendChild(frame);
+ await new Promise(resolve => frame.onload = resolve);
+
+ const video = SpecialPowers.wrap(frame).contentDocument.body.childNodes[0];
+ video.muted = true; // to allow playback
+ return video.play();
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-01.html b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-01.html
new file mode 100644
index 0000000000..ed59c3ae99
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-01.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name=viewport content=width=device-width>
+<title>Snap to a slider's tick marks by clicking near them</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/rendering.html#the-input-element-as-a-range-control">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1803118">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-actions.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<input type=range list=tickmarks min=-5 max=35>
+<datalist id=tickmarks>
+ <option value=0></option>
+ <option value=3></option>
+</datalist>
+<script>
+ const range = document.querySelector("input[type=range]");
+ const step = 1;
+ promise_test(async function snapToTickMarks() {
+ const assertions = [[-3, "-3"], [-2, "0"], [1, "0"], [2, "3"], [5, "3"], [6, "6"]];
+ const rect = range.getBoundingClientRect();
+ const padding = 10;
+ const left = rect.left + padding;
+ const width = rect.width - 2 * padding;
+ const actions = new test_driver.Actions();
+ const min = parseInt(range.min);
+ const max = parseInt(range.max);
+ for (const assertion of assertions) {
+ const moveTo = (left + width * (assertion[0] - min) / (max - min)) | 0;
+ const expected = assertion[1];
+ await actions
+ .pointerMove(moveTo, rect.top)
+ .pointerDown()
+ .pointerUp()
+ .send();
+ assert_equals(range.value, expected);
+ }
+ });
+ promise_test(async function domDoesNotSnap() {
+ const startAt = -2;
+ range.value = startAt;
+ for (let expectedValue = startAt + 1; expectedValue <= 6; expectedValue++) {
+ range.stepUp();
+ assert_equals(parseInt(range.value), expectedValue);
+ }
+ });
+ promise_test(async function keyboardDoesNotSnap() {
+ const kArrowRight = "\uE014";
+ range.focus();
+ const startAt = -2;
+ range.value = startAt;
+ for (let expectedValue = startAt + 1; expectedValue <= 6; expectedValue++) {
+ await test_driver.send_keys(range, kArrowRight);
+ assert_equals(parseInt(range.value), expectedValue);
+ }
+ });
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-02.html b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-02.html
new file mode 100644
index 0000000000..061f34b3a7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-02.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name=viewport content=width=device-width>
+<title>Snap to an RTL slider's tick marks by clicking near them</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/rendering.html#the-input-element-as-a-range-control">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1803118">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-actions.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<input type=range list=tickmarks min=-5 max=35 dir=rtl>
+<datalist id=tickmarks>
+ <option value=0></option>
+ <option value=3></option>
+</datalist>
+<script>
+ const range = document.querySelector("input[type=range]");
+ const step = 1;
+ promise_test(async function snapToRTLTickMarks() {
+ const assertions = [[-3, "-3"], [-2, "0"], [1, "0"], [2, "3"], [5, "3"], [6, "6"]];
+ const rect = range.getBoundingClientRect();
+ const padding = 10;
+ const right = rect.right - padding;
+ const width = rect.width - 2 * padding;
+ const actions = new test_driver.Actions();
+ const min = parseInt(range.min);
+ const max = parseInt(range.max);
+ for (const assertion of assertions) {
+ const moveTo = (right - width * (assertion[0] - min) / (max - min)) | 0;
+ const expected = assertion[1];
+ await actions
+ .pointerMove(moveTo, rect.top)
+ .pointerDown()
+ .pointerUp()
+ .send();
+ assert_equals(range.value, expected);
+ }
+ });
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-03.html b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-03.html
new file mode 100644
index 0000000000..9ee80199e4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/rendering/non-replaced-elements/form-controls/range-snap-to-tick-marks-03.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name=viewport content=width=device-width>
+<title>Snap to a vertical slider's tick marks by clicking near them</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/rendering.html#the-input-element-as-a-range-control">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1803118">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-actions.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<style>
+ input[type=range] {
+ writing-mode: vertical-lr;
+ }
+</style>
+<input type=range list=tickmarks min=-5 max=35>
+<datalist id=tickmarks>
+ <option value=0></option>
+ <option value=3></option>
+</datalist>
+<script>
+ const range = document.querySelector("input[type=range]");
+ promise_test(async function snapToVerticalTickMarks() {
+ const assertions = [[-3, "-3"], [-2, "0"], [1, "0"], [2, "3"], [5, "3"], [6, "6"]];
+ const rect = range.getBoundingClientRect();
+ const padding = 10;
+ const bottom = rect.bottom - padding;
+ const height = rect.height - 2 * padding;
+ const actions = new test_driver.Actions();
+ const min = parseInt(range.min);
+ const max = parseInt(range.max);
+ for (const assertion of assertions) {
+ const moveTo = (bottom - height * (assertion[0] - min) / (max - min)) | 0;
+ const expected = assertion[1];
+ await actions
+ .pointerMove(rect.left, moveTo)
+ .pointerDown()
+ .pointerUp()
+ .send();
+ assert_equals(range.value, expected);
+ }
+ });
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/form-submission-0/non-usv-filenames.window.js b/testing/web-platform/mozilla/tests/html/semantics/forms/form-submission-0/non-usv-filenames.window.js
new file mode 100644
index 0000000000..9b5aa88abb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/form-submission-0/non-usv-filenames.window.js
@@ -0,0 +1,95 @@
+// META: script=/html/semantics/forms/form-submission-0/enctypes-helper.js
+
+// This test is built on the same infrastructure as the WPT tests
+// urlencoded2.window.js, multipart-formdata.window.js and text-plain.window.js,
+// except modified because this file only tests the serialization of filenames.
+// See the enctypes-helper.js file in the regular WPT test suite for more info.
+
+// The `urlencoded`, `multipart` and `textPlain` functions take a `file`
+// property rather than `name` and `value` properties, and the value of
+// `expected` is the serialization of the filename in the given encoding.
+
+function formSubmissionTemplate2(enctype, expectedBuilder) {
+ const formTestFn = formSubmissionTemplate(enctype, expectedBuilder);
+ return ({ file, formEncoding, expected, description }) =>
+ formTestFn({ name: "a", value: file, formEncoding, expected, description });
+}
+
+const urlencoded = formSubmissionTemplate2(
+ "application/x-www-form-urlencoded",
+ filename => `a=${filename}`
+);
+const multipart = formSubmissionTemplate2(
+ "multipart/form-data",
+ (filename, serialized) => {
+ const boundary = serialized.split("\r\n")[0];
+ return [
+ boundary,
+ `Content-Disposition: form-data; name="a"; filename="${filename}"`,
+ "Content-Type: text/plain",
+ "",
+ "", // File contents
+ `${boundary}--`,
+ "",
+ ].join("\r\n");
+ }
+);
+const textPlain = formSubmissionTemplate2(
+ "text/plain",
+ filename => `a=${filename}\r\n`
+);
+
+// -----------------------------------------------------------------------------
+
+(async () => {
+ // This creates an empty filesystem file with an arbitrary name and returns it
+ // as a File object with name "a\uD800b".
+ const file = SpecialPowers.unwrap(
+ await SpecialPowers.createFiles(
+ [{ data: "", options: { name: "a\uD800b", type: "text/plain" } }],
+ files => files[0]
+ )
+ );
+
+ urlencoded({
+ file,
+ formEncoding: "UTF-8",
+ expected: "a%EF%BF%BDb",
+ description: "lone surrogate in filename, UTF-8",
+ });
+
+ urlencoded({
+ file,
+ formEncoding: "windows-1252",
+ expected: "a%26%2365533%3Bb",
+ description: "lone surrogate in filename, windows-1252",
+ });
+
+ multipart({
+ file,
+ formEncoding: "UTF-8",
+ expected: "a\xEF\xBF\xBDb",
+ description: "lone surrogate in filename, UTF-8",
+ });
+
+ multipart({
+ file,
+ formEncoding: "windows-1252",
+ expected: "a&#65533;b",
+ description: "lone surrogate in filename, windows-1252",
+ });
+
+ textPlain({
+ file,
+ formEncoding: "UTF-8",
+ expected: "a\xEF\xBF\xBDb",
+ description: "lone surrogate in filename, UTF-8",
+ });
+
+ textPlain({
+ file,
+ formEncoding: "windows-1252",
+ expected: "a&#65533;b",
+ description: "lone surrogate in filename, windows-1252",
+ });
+})();
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/input-radio-key-navigation.html b/testing/web-platform/mozilla/tests/html/semantics/forms/input-radio-key-navigation.html
new file mode 100644
index 0000000000..2eee99ffaf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/input-radio-key-navigation.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<title>Keyboard navigation on input type=radio</title>
+<meta charset=utf-8>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+
+<form dir="ltr">
+ <input type=radio name=whatever value=1>
+ <input type=radio name=whatever value=2>
+ <input type=radio name=whatever value=3>
+</form>
+<form dir="rtl">
+ <input type=radio name=whatever value=1>
+ <input type=radio name=whatever value=2>
+ <input type=radio name=whatever value=3>
+</form>
+<script>
+const KEYS = {
+ ArrowLeft: '\uE012',
+ ArrowUp: '\uE013',
+ ArrowRight: '\uE014',
+ ArrowDown: '\uE015',
+};
+
+function nextFocusIndex(currentIndex, length, forward) {
+ if (forward) {
+ return (currentIndex + 1) % length;
+ }
+ return (currentIndex == 0 ? length : currentIndex) - 1;
+}
+
+async function testMove(form, keyName, forward) {
+ let radios = form.querySelectorAll("input[type=radio]");
+ assert_equals(radios.length, 3, "Sanity check");
+
+ let focusIndex = 1;
+ radios[focusIndex].focus();
+
+ // Enough to wrap around, and one more to test the last active element too.
+ for (let i = 0; i <= radios.length; ++i) {
+ assert_equals(document.activeElement, radios[focusIndex], `Focused expected radio input (${focusIndex})`);
+ await test_driver.send_keys(document.activeElement, KEYS[keyName]);
+ focusIndex = nextFocusIndex(focusIndex, radios.length, forward);
+ }
+}
+
+promise_test(async t => {
+ for (let form of document.querySelectorAll("form")) {
+ const rtl = form.dir == "rtl";
+ await testMove(form, "ArrowDown", /* forward = */ true);
+ await testMove(form, "ArrowUp", /* forward = */ false);
+ await testMove(form, "ArrowLeft", /* forward = */ rtl);
+ await testMove(form, "ArrowRight", /* forward = */ !rtl);
+ }
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/textfieldselection/selection-value-interactions.html b/testing/web-platform/mozilla/tests/html/semantics/forms/textfieldselection/selection-value-interactions.html
new file mode 100644
index 0000000000..c6ba07f746
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/textfieldselection/selection-value-interactions.html
@@ -0,0 +1,217 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id=target></div>
+<script>
+ var target = document.getElementById("target");
+ var sometext = "something";
+ var shorttext = "abc";
+ var elemData = [
+ {
+ desc: "textarea not in body",
+ factory: () => document.createElement("textarea"),
+ },
+ {
+ desc: "input not in body",
+ factory: () => document.createElement("input"),
+ },
+ {
+ desc: "textarea in body",
+ factory: () => document.body.appendChild(document.createElement("textarea")),
+ },
+ {
+ desc: "input in body",
+ factory: () => document.body.appendChild(document.createElement("input")),
+ },
+ {
+ desc: "textarea in body with parsed default value",
+ factory: () => {
+ target.innerHTML = "<textarea>abcdefghij</textarea>"
+ return target.querySelector("textarea");
+ },
+ },
+ {
+ desc: "input in body with parsed default value",
+ factory: () => {
+ target.innerHTML = "<input value='abcdefghij'>"
+ return target.querySelector("input");
+ },
+ },
+ {
+ desc: "focused textarea",
+ factory: () => {
+ var t = document.body.appendChild(document.createElement("textarea"));
+ t.focus();
+ return t;
+ },
+ },
+ {
+ desc: "focused input",
+ factory: () => {
+ var i = document.body.appendChild(document.createElement("input"));
+ i.focus();
+ return i;
+ },
+ },
+ {
+ desc: "focused then blurred textarea",
+ factory: () => {
+ var t = document.body.appendChild(document.createElement("textarea"));
+ t.focus();
+ t.blur();
+ return t;
+ },
+ },
+ {
+ desc: "focused then blurred input",
+ factory: () => {
+ var i = document.body.appendChild(document.createElement("input"));
+ i.focus();
+ i.blur()
+ return i;
+ },
+ },
+ ];
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ assert_equals(el.selectionStart, 0,
+ `Cursor start should be at beginning of ${data.desc}`);
+ assert_equals(el.selectionEnd, 0,
+ `Cursor end should be at beginning of ${data.desc}`);
+ }, `cursor location for initial value of ${data.desc}`);
+}
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ el.defaultValue = sometext;
+ // The "focused or has been focused" case behaves differently.
+ if (data.desc.includes("focused")) {
+ assert_equals(el.selectionStart, el.value.length,
+ `Cursor start should be at end of ${data.desc}`);
+ assert_equals(el.selectionEnd, el.value.length,
+ `Cursor end should be at end of ${data.desc}`);
+ } else {
+ assert_equals(el.selectionStart, 0,
+ `Cursor start should be at beginning of ${data.desc}`);
+ assert_equals(el.selectionEnd, 0,
+ `Cursor end should be at beginning of ${data.desc}`);
+ }
+ }, `cursor location after defaultValue set of ${data.desc}`);
+}
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ el.selectionStart = el.selectionStart;
+ el.defaultValue = sometext;
+ // The focused case behaves differently.
+ if (data.desc.includes("focused")) {
+ assert_equals(el.selectionStart, el.value.length,
+ `Cursor start should be at end of ${data.desc}`);
+ assert_equals(el.selectionEnd, el.value.length,
+ `Cursor end should be at end of ${data.desc}`);
+ } else {
+ assert_equals(el.selectionStart, 0,
+ `Cursor start should be at beginning of ${data.desc}`);
+ assert_equals(el.selectionEnd, 0,
+ `Cursor end should be at beginning of ${data.desc}`);
+ }
+ }, `cursor location after defaultValue set after no-op selectionStart set of ${data.desc}`);
+}
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ el.value = sometext;
+ assert_equals(el.selectionStart, sometext.length,
+ `Cursor start should be at end of ${data.desc}`);
+ assert_equals(el.selectionEnd, sometext.length,
+ `Cursor end should be at end of ${data.desc}`);
+ }, `cursor location after value set of ${data.desc}`);
+}
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ assert_true(sometext.length > 8,
+ "sometext too short, test won't work right");
+ el.defaultValue = sometext;
+ el.selectionStart = 1;
+ el.selectionEnd = 8;
+ assert_equals(el.selectionStart, 1, "We just set selectionStart!");
+ assert_equals(el.selectionEnd, 8, "We just set selectionEnd!");
+ assert_true(shorttext.length > 1,
+ "shorttext too short, test won't work right");
+ assert_true(shorttext.length < 8,
+ "shorttext too long, test won't work right");
+ el.defaultValue = shorttext;
+ // The "focused or has been focused" case behaves differently.
+ if (data.desc.includes("focused")) {
+ assert_equals(el.selectionStart, el.value.length,
+ `Cursor start should be at end of ${data.desc}`);
+ assert_equals(el.selectionEnd, el.value.length,
+ `Cursor end should be at end of ${data.desc}`);
+ } else {
+ if (el.tagName.toLowerCase() === "textarea") {
+ assert_equals(el.selectionStart, 0,
+ "Selection should be collapsed to the beginning");
+ assert_equals(el.selectionEnd, 0,
+ "Selection should be collapsed to the beginning");
+ } else {
+ assert_equals(el.selectionStart, 1,
+ "Shouldn't have moved selection start");
+ assert_equals(el.selectionEnd, shorttext.length,
+ "Should have adjusted selection end");
+ }
+ }
+ }, `selection location after defaultValue set to shorter than selectionEnd of ${data.desc}`);
+}
+
+for (var data of elemData) {
+ test(function() {
+ var el = data.factory();
+ this.add_cleanup(() => el.remove());
+ assert_true(sometext.length > 8,
+ "sometext too short, test won't work right");
+ el.defaultValue = sometext;
+ el.selectionStart = 5;
+ el.selectionEnd = 8;
+ assert_equals(el.selectionStart, 5, "We just set selectionStart!");
+ assert_equals(el.selectionEnd, 8, "We just set selectionEnd!");
+ assert_true(shorttext.length < 5,
+ "shorttext too long, test won't work right");
+ el.defaultValue = shorttext;
+ // The "focused or has been focused" case behaves differently.
+ if (data.desc.includes("focused")) {
+ assert_equals(el.selectionStart, el.value.length,
+ `Cursor start should be at end of ${data.desc}`);
+ assert_equals(el.selectionEnd, el.value.length,
+ `Cursor end should be at end of ${data.desc}`);
+ } else {
+ if (el.tagName.toLowerCase() === "textarea") {
+ assert_equals(el.selectionStart,0,
+ "Selection should be collapsed to the beginning");
+ assert_equals(el.selectionEnd, 0,
+ "Selection should be collapsed to the beginning");
+ } else {
+ assert_equals(el.selectionStart, shorttext.length,
+ "Should have adjusted selection start");
+ assert_equals(el.selectionEnd, shorttext.length,
+ "Should have adjusted selection end");
+ }
+ }
+ }, `selection location after defaultValue set to shorter than selectionStart of ${data.desc}`);
+}
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01-notref.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01-notref.html
new file mode 100644
index 0000000000..67591468cf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01-notref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>vertical range input with datalist reference</title>
+<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01.html
new file mode 100644
index 0000000000..f1bd96f391
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-01.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>vertical range input with datalist</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
+<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="mismatch" href="range-tick-marks-01-notref.html">
+<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
+<datalist id="powers">
+ <option value="0">
+ <option value="-30">
+ <option value="30">
+ <option value="50">
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02-notref.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02-notref.html
new file mode 100644
index 0000000000..59acde1482
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02-notref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>max and min attributes applied to vertical range input with datalist reference</title>
+<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
+<datalist id="powers">
+ <option value="0">
+ <option value="-30">
+ <option value="30">
+ <option value="50">
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02.html
new file mode 100644
index 0000000000..bd45631d4a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-02.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>max and min attributes applied to vertical range input with datalist</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
+<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="mismatch" href="range-tick-marks-02-notref.html">
+<input type="range" orient="vertical" min="-40" max="40" value="0" step="10" name="power" list="powers">
+<datalist id="powers">
+ <option value="0">
+ <option value="-30">
+ <option value="30">
+ <option value="50">
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03-ref.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03-ref.html
new file mode 100644
index 0000000000..df473920ec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>no vertical range tick marks for disabled datalist elements reference</title>
+<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
+<datalist id="powers">
+ <option value="-30">
+ <option value="50">
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03.html
new file mode 100644
index 0000000000..83b5c2eb66
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-03.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>no vertical range tick marks for disabled datalist elements</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#htmldatalistelement">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-disabled">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841942">
+<link rel="author" href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="match" href="range-tick-marks-03-ref.html">
+<input type="range" orient="vertical" min="-100" max="100" value="0" step="10" name="power" list="powers">
+<datalist id="powers">
+ <option value="0" disabled>
+ <option value="-30">
+ <option value="30" disabled>
+ <option value="50">
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04-ref.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04-ref.html
new file mode 100644
index 0000000000..c2bf59e52b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>no range tick marks for vertical range tick marks that are step mismatches reference</title>
+<input type=range step=3 value=1 min=-5 max=5 list=degrees>
+<datalist id=degrees>
+ <option value=-2>
+ <option value=4>
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04.html b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04.html
new file mode 100644
index 0000000000..a47334b411
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/the-input-element/range-tick-marks-04.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>no range tick marks for vertical range tick marks that are step mismatches</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1803303">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel=match href=range-tick-marks-04-ref.html>
+<input type=range step=3 value=1 min=-5 max=5 list=degrees>
+<datalist id=degrees>
+ <option value=-4>
+ <option value=-2>
+ <option value=0>
+ <option value=2>
+ <option value=4>
+</datalist>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/forms/time-enter-keypress.html b/testing/web-platform/mozilla/tests/html/semantics/forms/time-enter-keypress.html
new file mode 100644
index 0000000000..2ffeb22cb4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/forms/time-enter-keypress.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<title>Enter submits on time input</title>
+<meta charset=utf-8>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<form>
+ <input type="time" name="time">
+ <input type=submit>
+</form>
+<form>
+ <input type="date" name="date">
+ <input type=submit>
+</form>
+<form>
+ <input type="datetime-local" name="datetime-local">
+ <input type=submit>
+</form>
+<script>
+async function testEnterOnInput(form) {
+ const submitted = new Promise(resolve => {
+ form.addEventListener("submit", function(e) {
+ e.preventDefault();
+ resolve();
+ }, { once: true });
+ });
+ const input = form.querySelector("input");
+ input.focus();
+
+ const ENTER = "\uE007";
+ await new test_driver.Actions()
+ .keyDown(ENTER)
+ .keyUp(ENTER)
+ .send()
+ await submitted;
+ assert_true(true, "Form was submitted on enter for input " + input.type);
+}
+
+promise_test(async t => {
+ for (let form of document.querySelectorAll("form")) {
+ await testEnterOnInput(form, t);
+ }
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-circular.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-circular.html
new file mode 100644
index 0000000000..c99893a786
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-circular.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load dynamically imported async modules circular</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load async dynamic module")
+ window.addEventListener("error", scriptError);
+ function scriptError(e) {
+ // An error is expected
+ test.step(() => assert_true(e.message !== "FAIL"));
+ }
+ function scriptLoaded() {
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_dynamic_module_circular.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-error.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-error.html
new file mode 100644
index 0000000000..ff2ac06222
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module-error.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load dynamically imported async modules which errors</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load dynamically imported async modules with error")
+ window.addEventListener("error", scriptError);
+ function scriptError(e) {
+ // An error is expected
+ test.step(() => assert_true(e.message !== "FAIL"));
+ }
+ function scriptLoaded() {
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_dynamic_module_error.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module.html
new file mode 100644
index 0000000000..2e1b267492
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-dynamic-module.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load dynamically imported async modules</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load async dynamic module")
+ window.addEventListener("error", scriptError);
+ function scriptError(e) {
+ // An error is expected
+ test.step(() => assert_true(e.message !== "FAIL"));
+ }
+ function scriptLoaded() {
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_dynamic_module.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-circular.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-circular.html
new file mode 100644
index 0000000000..7540ebb5ec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-circular.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load async modules circular</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load async module")
+ window.addEventListener("error", scriptError);
+ function scriptError(e) {
+ // An error is expected
+ test.step(() => assert_true(e.message !== "FAIL"));
+ test.done();
+ }
+ function scriptLoaded() {
+ test.step(() => assert_unreached("Should not load before error"));
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_module_circular.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()">
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-error.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-error.html
new file mode 100644
index 0000000000..c720611080
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module-error.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load an async module</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load dynamic async module with syntax error")
+ window.addEventListener("error", scriptError);
+ function scriptError(e) {
+ // An error is expected
+ test.step(() => assert_true(e.message !== "FAIL"));
+ }
+ function scriptLoaded() {
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_module_error.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module.html
new file mode 100644
index 0000000000..566e2a379d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/async-module.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load dynamically imported async modules</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load async dynamic module")
+ function scriptLoaded() {
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/async_module.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()">
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/circular-module-import-with-syntax-error.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/circular-module-import-with-syntax-error.html
new file mode 100644
index 0000000000..e472656e34
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/circular-module-import-with-syntax-error.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load a module with circular imports and syntax error</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Load module with circular imports and syntax error")
+ window.addEventListener("error", scriptError);
+ function scriptError() {
+ // An error is expected
+ test.done();
+ }
+ function scriptLoaded() {
+ test.step(() => assert_unreached("Should not load"));
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ src="./support/circular_error1.js"
+ onerror="testNoError()"
+ onload="scriptLoaded()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/create-module-script.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/create-module-script.html
new file mode 100644
index 0000000000..44337a0217
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/create-module-script.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Insert non-async module script</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ var test = async_test("Create module script")
+ var moduleRan = false;
+ function loadModule() {
+ var script = document.createElement("script");
+ script.onerror = function() {
+ test.step(() => assert_unreached("Should not get an error"));
+ test.done();
+ };
+ script.onload = function() {
+ test.step(() => assert_equals(moduleRan, true));
+ test.done();
+ };
+ script.type = "module";
+ script.src = "support/module.js";
+ script.async = false;
+ document.documentElement.appendChild(script);
+ }
+</script>
+<body onload='loadModule()'></body>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/mixed-content-import.https.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/mixed-content-import.https.html
new file mode 100644
index 0000000000..5342bd525c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/mixed-content-import.https.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Attempt to load a mixed content module graph</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+ var test = async_test("Attempt to load a mixed content module graph")
+ window.addEventListener("error", testNoError);
+ function scriptError() {
+ // An error is expected
+ test.done();
+ }
+ function scriptLoaded() {
+ test.step(() => assert_unreached("Should not load"));
+ test.done();
+ }
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+</script>
+<script type="module"
+ onerror="scriptError()"
+ onload="scriptLoaded()"
+ src="./support/mixed_import.js">
+</script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/module-error-reporting.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/module-error-reporting.html
new file mode 100644
index 0000000000..e4c43060b6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/module-error-reporting.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Insert non-async module script</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ const test = async_test("Test error event properties");
+
+ let errorCount = 0;
+ let eventCount = 0;
+ window.addEventListener("error", handleError);
+ window.addEventListener("load", handleLoaded);
+
+ function handleEvent(event) {
+ eventCount++;
+ test.step(() => assert_equals(typeof event, "object"));
+ test.step(() => assert_true(event instanceof Event));
+ }
+
+ function handleError(event) {
+ errorCount++;
+ test.step(() => assert_equals(typeof event, "object"));
+ test.step(() => assert_true(event instanceof ErrorEvent));
+ switch (errorCount) {
+ case 1:
+ test.step(() => assert_true(event.error instanceof SyntaxError));
+ test.step(() => assert_true(event.filename.endsWith("/bad_local_export.js")));
+ test.step(() => assert_equals(event.lineno, 3));
+ test.step(() => assert_equals(event.colno, 7));
+ break;
+ case 2:
+ test.step(() => assert_true(event.error instanceof TypeError));
+ test.step(() => assert_true(event.filename.endsWith("/import_resolve_failure.js")));
+ test.step(() => assert_equals(event.lineno, 2));
+ test.step(() => assert_equals(event.colno, 16));
+ break;
+ case 3:
+ test.step(() => assert_true(event.error instanceof TypeError));
+ test.step(() => assert_true(event.filename.endsWith("/indirect_export_resolve_failure.js")));
+ test.step(() => assert_equals(event.lineno, 2));
+ test.step(() => assert_equals(event.colno, 19));
+ break;
+ case 4:
+ test.step(() => assert_true(event.error instanceof SyntaxError));
+ test.step(() => assert_true(event.filename.endsWith("/missing_import.js")));
+ test.step(() => assert_equals(event.lineno, 2));
+ test.step(() => assert_equals(event.colno, 8));
+ break;
+ case 5:
+ test.step(() => assert_true(event.error instanceof SyntaxError));
+ test.step(() => assert_true(event.filename.endsWith("/missing_indirect_export.js")));
+ test.step(() => assert_equals(event.lineno, 2));
+ test.step(() => assert_equals(event.colno, 11));
+ break;
+ case 6:
+ test.step(() => assert_true(event.error instanceof SyntaxError));
+ test.step(() => assert_true(event.filename.endsWith("/module_eval_error.js")));
+ test.step(() => assert_equals(event.lineno, 3));
+ test.step(() => assert_equals(event.colno, 0));
+ break;
+ }
+ }
+
+ function testNoError() {
+ test.step(() => assert_unreached("No event expected here"));
+ test.done();
+ }
+
+ function handleLoaded() {
+ test.step(() => assert_equals(eventCount, 2));
+ test.step(() => assert_equals(errorCount, 6));
+ test.done();
+ }
+
+</script>
+
+<!-- Errors that fire an event on the script element -->
+<script type="module" src="" onerror="handleEvent(event)"></script>
+<script type="module" src="./does_not_exist" onerror="handleEvent(event)"></script>
+
+<!-- Errors that fire an error event on the global -->
+<script type="module" src="./support/bad_local_export.js" onerror="handleEvent(event)"></script>
+<script type="module" src="./support/import_resolve_failure.js" onerror="testNoError()"></script>
+<script type="module" src="./support/indirect_export_resolve_failure.js" onerror="testNoError()"></script>
+<script type="module" src="./support/missing_import.js" onerror="testNoError()"></script>
+<script type="module" src="./support/missing_indirect_export.js" --onerror="testNoError()"></script>
+<script type="module" src="./support/module_eval_error.js" onerror="testNoError()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/reload-failed-module-script.html b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/reload-failed-module-script.html
new file mode 100644
index 0000000000..b95d3fe330
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/reload-failed-module-script.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Insert non-async module script</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ var test = async_test("Reload failed module script");
+
+ var errorCount = 0;
+ window.addEventListener("error", handleError);
+
+ function handleError() {
+ errorCount++;
+
+ if (errorCount == 1) {
+ reloadModule();
+ return;
+ }
+
+ test.step(() => assert_equals(errorCount, 2));
+ test.done();
+ }
+
+ function reloadModule() {
+ var script = document.createElement("script");
+ script.onerror = testNoError;
+ script.type = "module";
+ script.src = "support/missing_import.js";
+ script.async = false;
+ document.documentElement.appendChild(script);
+ }
+
+ function testNoError() {
+ test.step(() => assert_unreached("No event expect here"));
+ test.done();
+ }
+
+</script>
+<script type="module" src="support/missing_import.js" onerror="testNoError()"></script>
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module.js
new file mode 100644
index 0000000000..238dc11402
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module.js
@@ -0,0 +1,11 @@
+var ns = await import('./async_test_module.js');
+if (ns.default !== 42) {
+ throw new Error("FAIL");
+}
+if (ns.x !== "named") {
+ throw new Error("FAIL");
+}
+if (ns.y !== 39) {
+ throw new Error("FAIL");
+}
+
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_circular.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_circular.js
new file mode 100644
index 0000000000..93bfc3aca8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_circular.js
@@ -0,0 +1,5 @@
+try {
+ var ns = await import('./async_test_module_circular_1.js');
+} catch(ns) {
+ throw Error("Fails as expected");
+};
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_error.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_error.js
new file mode 100644
index 0000000000..3832960108
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_dynamic_module_error.js
@@ -0,0 +1,5 @@
+try {
+ await import('./bad_local_export.js');
+} catch(ns) {
+ throw Error("Fails as expected");
+};
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module.js
new file mode 100644
index 0000000000..34a590bcfc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module.js
@@ -0,0 +1,14 @@
+import nsPromise from './async_test_module.js';
+
+console.log("hi");
+let ns = await nsPromise;
+
+if (ns.default !== 42) {
+ throw new Error("FAIL");
+}
+if (ns.x !== "named") {
+ throw new Error("FAIL");
+}
+if (ns.y !== 39) {
+ throw new Error("FAIL");
+}
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_circular.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_circular.js
new file mode 100644
index 0000000000..a9dff71b17
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_circular.js
@@ -0,0 +1,3 @@
+import module from './async_test_module_circular_1.js';
+
+throw new Error("FAIL");
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_error.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_error.js
new file mode 100644
index 0000000000..3fa6991768
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_module_error.js
@@ -0,0 +1,4 @@
+import ns from "./async_test_module_failure.js";
+
+throw Error("FAIL");
+
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module.js
new file mode 100644
index 0000000000..201c76eedf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module.js
@@ -0,0 +1,12 @@
+await 1;
+await 2;
+export default await Promise.resolve(42);
+
+export const y = await 39;
+export const x = await 'named';
+
+// Bonus: this rejection is not unwrapped
+if (false) {
+ await Promise.reject(42);
+}
+
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_1.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_1.js
new file mode 100644
index 0000000000..2fdf67baca
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_1.js
@@ -0,0 +1,3 @@
+import module from './async_test_module_circular_2.js';
+
+export default {};
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_2.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_2.js
new file mode 100644
index 0000000000..0a09aacc39
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_2.js
@@ -0,0 +1,5 @@
+import module from './async_test_module_circular_3.js';
+
+await module.test();
+
+export default {};
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_3.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_3.js
new file mode 100644
index 0000000000..d815bc00e4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_circular_3.js
@@ -0,0 +1,8 @@
+import module from './async_test_module_circular_1.js';
+
+export default {
+ async test() {
+ throw new Error("error thrown");
+ return Promise.resolve()
+ }
+};
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_failure.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_failure.js
new file mode 100644
index 0000000000..6f823f3003
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/async_test_module_failure.js
@@ -0,0 +1,6 @@
+export default 42;
+
+export const named = 'named';
+
+var rejection = Promise.reject(TypeError('I reject this!'));
+await rejection;
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/bad_local_export.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/bad_local_export.js
new file mode 100644
index 0000000000..0b3df8de32
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/bad_local_export.js
@@ -0,0 +1,3 @@
+// Attempt to export something that doesn't exist.
+
+export missing;
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error1.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error1.js
new file mode 100644
index 0000000000..f0310fe0b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error1.js
@@ -0,0 +1,2 @@
+import { test2 } from "./circular_error2.js";
+import "./circular_error3.js";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error2.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error2.js
new file mode 100644
index 0000000000..5b163eab93
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error2.js
@@ -0,0 +1 @@
+import "./circular_error3.js";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error3.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error3.js
new file mode 100644
index 0000000000..2589defac8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/circular_error3.js
@@ -0,0 +1 @@
+import "./circular_error1.js";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/evaluation-order-setup.mjs b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/evaluation-order-setup.mjs
new file mode 100644
index 0000000000..d3f22e9ee0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/evaluation-order-setup.mjs
@@ -0,0 +1,19 @@
+globalThis.setup({allow_uncaught_exception: true});
+
+globalThis.log = [];
+
+globalThis.addEventListener("error",
+ event => globalThis.log.push("global-error", event.error.message));
+globalThis.addEventListener("onunhandledrejection",
+ event => globalThis.log.push('unhandled-promise-rejection'));
+globalThis.addEventListener("load",
+ event => globalThis.log.push("global-load"));
+
+globalThis.unreachable = function() {
+ globalThis.log.push("unreachable");
+}
+
+globalThis.test_load = async_test("Test evaluation order of modules");
+globalThis.testDone = globalThis.test_load.step_func_done(() => {
+ assert_array_equals(globalThis.log, globalThis.expectedLog);
+});
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/import_resolve_failure.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/import_resolve_failure.js
new file mode 100644
index 0000000000..a2e2875f20
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/import_resolve_failure.js
@@ -0,0 +1,2 @@
+// Import from an unresolvable module specifier.
+import {x} from "unresolvable";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/indirect_export_resolve_failure.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/indirect_export_resolve_failure.js
new file mode 100644
index 0000000000..282fd2ed62
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/indirect_export_resolve_failure.js
@@ -0,0 +1,2 @@
+// Export from an unresolvable module specifier.
+export {x, y} from "unresolvable";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_import.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_import.js
new file mode 100644
index 0000000000..885db02dde
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_import.js
@@ -0,0 +1,2 @@
+// Import a non-existent export to trigger instantiation failure.
+import {not_found} from "./module.js";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_indirect_export.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_indirect_export.js
new file mode 100644
index 0000000000..8494031b09
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/missing_indirect_export.js
@@ -0,0 +1,2 @@
+// Import a non-existent export to trigger instantiation failure.
+export {x, not_found} from "./module.js";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import.js
new file mode 100644
index 0000000000..371018f1f4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import.js
@@ -0,0 +1 @@
+export * from "http://web-platform.test:8000/_mozilla/html/semantics/scripting-1/the-script-element/support/mixed_import2.js"
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import2.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import2.js
new file mode 100644
index 0000000000..60c6c8d8b0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/mixed_import2.js
@@ -0,0 +1 @@
+export default "foo";
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module.js
new file mode 100644
index 0000000000..1269686475
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module.js
@@ -0,0 +1,2 @@
+export let x = 42;
+moduleRan = true;
diff --git a/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module_eval_error.js b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module_eval_error.js
new file mode 100644
index 0000000000..3bd872b2e6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/semantics/scripting-1/the-script-element/support/module_eval_error.js
@@ -0,0 +1,3 @@
+// A module that throws when evaluated.
+
+this = 0;
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/README.md b/testing/web-platform/mozilla/tests/html/syntax/charset/README.md
new file mode 100644
index 0000000000..0558ae1cd5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/README.md
@@ -0,0 +1,7 @@
+The tests in this directory intentionally differ from WebKit and Blink.
+
+These are case where using the real tree builder (with `noscript`) parsing
+as in the scripting enabled mode and with CDATA sections parsing with
+awareness of foreign content differs from WebKit's and Blink's behavior
+that works as if there was a pre-foreign content, pre-template tree builder
+running in the scripting disabled mode.
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-after-template.html b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-after-template.html
new file mode 100644
index 0000000000..71ef9144e0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-after-template.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-after-template-ref.html">
+<noscript><template></template><meta charset="windows-1251"></noscript>
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>).</p>
+<p>Test: </p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-ncr.html b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-ncr.html
new file mode 100644
index 0000000000..645f151b26
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript-ncr.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-ncr-ref.html">
+<noscript><meta charset="&#119;indows-1251"></noscript>
+</head>
+<body>
+<p>Meta with NCR in the encoding label in <code>noscript</code>.</p>
+<p>Test: </p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript.html b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript.html
new file mode 100644
index 0000000000..e76054d618
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/in-noscript.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-ref.html">
+<noscript><meta charset="windows-1251"></noscript>
+</head>
+<body>
+<p>Meta in <code>noscript</code>.</p>
+<p>Test: </p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/in-svg-in-cdata-after-gt.html b/testing/web-platform/mozilla/tests/html/syntax/charset/in-svg-in-cdata-after-gt.html
new file mode 100644
index 0000000000..56783b7afc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/in-svg-in-cdata-after-gt.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-svg-in-cdata-after-gt-ref.html">
+</head>
+<body>
+<svg><![CDATA[><meta charset="windows-1251">]]></svg>
+<p>In SVG in CDATA after greater-than sign in the CDATA (after head).</p>
+<p>Test: </p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-after-template-ref.html b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-after-template-ref.html
new file mode 100644
index 0000000000..27defe54c0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-after-template-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ncr-ref.html b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ncr-ref.html
new file mode 100644
index 0000000000..3581ab68db
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ncr-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta with NCR in the encoding label in <code>noscript</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ref.html b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ref.html
new file mode 100644
index 0000000000..9bb9f24b88
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-noscript-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>noscript</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-svg-in-cdata-after-gt-ref.html b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-svg-in-cdata-after-gt-ref.html
new file mode 100644
index 0000000000..2868f47fc2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/charset/references/in-svg-in-cdata-after-gt-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<svg></svg>
+<p>In SVG in CDATA after greater-than sign in the CDATA (after head).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html b/testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html
new file mode 100644
index 0000000000..3aff716d9f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/html/syntax/parsing/math-parse01.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>math in html: parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>math in html: parsing</h1>
+
+<div id="log" style="display:block"></div>
+
+<div style="display:none">
+<div><math id="m1"><mtext/></math></div>
+<div id="d1"><math><mrow/><mi/></math></div>
+<div id="d2"><math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math></div>
+<div id="d3">&lang;&rang;</div>
+<div id="d4">&Kopf;</div>
+<div id="d5"><math><semantics><mi>a</mi><annotation-xml><foo/><bar/></annotation-xml></semantics></math></div>
+<div id="d6"><math><semantics><mi>a</mi><annotation-xml encoding="text/html"><div></div></annotation-xml></semantics><mn/></math>
+</div>
+
+
+<script>
+
+test(function() {
+assert_equals(document.getElementById("m1"),document.getElementsByTagName("math")[0]);
+},"The id attribute should be recognised on math elements");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.nodeName,"math")
+},"The node name should be math");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.namespaceURI ,"http://www.w3.org/1998/Math/MathML")
+},"math should be in MathML Namespace");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.childNodes.length ,2)
+},"Math has 2 children (empty tag syntax)");
+
+test(function() {
+assert_equals(document.getElementById("d2").firstChild.childNodes.length ,1)
+},"Nested mrow elements should be parsed correctly");
+
+test(function() {
+assert_equals(document.getElementById("d3").firstChild.nodeValue ,"\u27E8\u27E9")
+},"Testing rang and lang entity code points");
+
+test(function() {
+assert_equals(document.getElementById("d4").firstChild.nodeValue ,"\uD835\uDD42")
+},"Testing Kopf (Plane 1) entity code point");
+
+test(function() {
+assert_equals(document.getElementById("d5").firstChild.firstChild.childNodes[1].childNodes.length ,2)
+},"Empty element tags in annotation-xml parsed as per XML.");
+
+test(function() {
+assert_equals(document.getElementById("d6").firstChild.childNodes.length ,2)
+},"html tags allowed in annotation-xml/@encoding='text/html'.");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/indic-detection/LICENSE b/testing/web-platform/mozilla/tests/indic-detection/LICENSE
new file mode 100644
index 0000000000..604209a804
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/LICENSE
@@ -0,0 +1,359 @@
+Creative Commons Legal Code
+
+Attribution-ShareAlike 3.0 Unported
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+ DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+ other pre-existing works, such as a translation, adaptation,
+ derivative work, arrangement of music or other alterations of a
+ literary or artistic work, or phonogram or performance and includes
+ cinematographic adaptations or any other form in which the Work may be
+ recast, transformed, or adapted including in any form recognizably
+ derived from the original, except that a work that constitutes a
+ Collection will not be considered an Adaptation for the purpose of
+ this License. For the avoidance of doubt, where the Work is a musical
+ work, performance or phonogram, the synchronization of the Work in
+ timed-relation with a moving image ("synching") will be considered an
+ Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+ encyclopedias and anthologies, or performances, phonograms or
+ broadcasts, or other works or subject matter other than works listed
+ in Section 1(f) below, which, by reason of the selection and
+ arrangement of their contents, constitute intellectual creations, in
+ which the Work is included in its entirety in unmodified form along
+ with one or more other contributions, each constituting separate and
+ independent works in themselves, which together are assembled into a
+ collective whole. A work that constitutes a Collection will not be
+ considered an Adaptation (as defined below) for the purposes of this
+ License.
+ c. "Creative Commons Compatible License" means a license that is listed
+ at https://creativecommons.org/compatiblelicenses that has been
+ approved by Creative Commons as being essentially equivalent to this
+ License, including, at a minimum, because that license: (i) contains
+ terms that have the same purpose, meaning and effect as the License
+ Elements of this License; and, (ii) explicitly permits the relicensing
+ of adaptations of works made available under that license under this
+ License or a Creative Commons jurisdiction license with the same
+ License Elements as this License.
+ d. "Distribute" means to make available to the public the original and
+ copies of the Work or Adaptation, as appropriate, through sale or
+ other transfer of ownership.
+ e. "License Elements" means the following high-level license attributes
+ as selected by Licensor and indicated in the title of this License:
+ Attribution, ShareAlike.
+ f. "Licensor" means the individual, individuals, entity or entities that
+ offer(s) the Work under the terms of this License.
+ g. "Original Author" means, in the case of a literary or artistic work,
+ the individual, individuals, entity or entities who created the Work
+ or if no individual or entity can be identified, the publisher; and in
+ addition (i) in the case of a performance the actors, singers,
+ musicians, dancers, and other persons who act, sing, deliver, declaim,
+ play in, interpret or otherwise perform literary or artistic works or
+ expressions of folklore; (ii) in the case of a phonogram the producer
+ being the person or legal entity who first fixes the sounds of a
+ performance or other sounds; and, (iii) in the case of broadcasts, the
+ organization that transmits the broadcast.
+ h. "Work" means the literary and/or artistic work offered under the terms
+ of this License including without limitation any production in the
+ literary, scientific and artistic domain, whatever may be the mode or
+ form of its expression including digital form, such as a book,
+ pamphlet and other writing; a lecture, address, sermon or other work
+ of the same nature; a dramatic or dramatico-musical work; a
+ choreographic work or entertainment in dumb show; a musical
+ composition with or without words; a cinematographic work to which are
+ assimilated works expressed by a process analogous to cinematography;
+ a work of drawing, painting, architecture, sculpture, engraving or
+ lithography; a photographic work to which are assimilated works
+ expressed by a process analogous to photography; a work of applied
+ art; an illustration, map, plan, sketch or three-dimensional work
+ relative to geography, topography, architecture or science; a
+ performance; a broadcast; a phonogram; a compilation of data to the
+ extent it is protected as a copyrightable work; or a work performed by
+ a variety or circus performer to the extent it is not otherwise
+ considered a literary or artistic work.
+ i. "You" means an individual or entity exercising rights under this
+ License who has not previously violated the terms of this License with
+ respect to the Work, or who has received express permission from the
+ Licensor to exercise rights under this License despite a previous
+ violation.
+ j. "Publicly Perform" means to perform public recitations of the Work and
+ to communicate to the public those public recitations, by any means or
+ process, including by wire or wireless means or public digital
+ performances; to make available to the public Works in such a way that
+ members of the public may access these Works from a place and at a
+ place individually chosen by them; to perform the Work to the public
+ by any means or process and the communication to the public of the
+ performances of the Work, including by public digital performance; to
+ broadcast and rebroadcast the Work by any means including signs,
+ sounds or images.
+ k. "Reproduce" means to make copies of the Work by any means including
+ without limitation by sound or visual recordings and the right of
+ fixation and reproducing fixations of the Work, including storage of a
+ protected performance or phonogram in digital form or other electronic
+ medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+ Collections, and to Reproduce the Work as incorporated in the
+ Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+ including any translation in any medium, takes reasonable steps to
+ clearly label, demarcate or otherwise identify that changes were made
+ to the original Work. For example, a translation could be marked "The
+ original work was translated from English to Spanish," or a
+ modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+ in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+ i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme cannot be waived, the Licensor
+ reserves the exclusive right to collect such royalties for any
+ exercise by You of the rights granted under this License;
+ ii. Waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme can be waived, the Licensor waives the
+ exclusive right to collect such royalties for any exercise by You
+ of the rights granted under this License; and,
+ iii. Voluntary License Schemes. The Licensor waives the right to
+ collect royalties, whether individually or, in the event that the
+ Licensor is a member of a collecting society that administers
+ voluntary licensing schemes, via that society, from any exercise
+ by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+ of this License. You must include a copy of, or the Uniform Resource
+ Identifier (URI) for, this License with every copy of the Work You
+ Distribute or Publicly Perform. You may not offer or impose any terms
+ on the Work that restrict the terms of this License or the ability of
+ the recipient of the Work to exercise the rights granted to that
+ recipient under the terms of the License. You may not sublicense the
+ Work. You must keep intact all notices that refer to this License and
+ to the disclaimer of warranties with every copy of the Work You
+ Distribute or Publicly Perform. When You Distribute or Publicly
+ Perform the Work, You may not impose any effective technological
+ measures on the Work that restrict the ability of a recipient of the
+ Work from You to exercise the rights granted to that recipient under
+ the terms of the License. This Section 4(a) applies to the Work as
+ incorporated in a Collection, but this does not require the Collection
+ apart from the Work itself to be made subject to the terms of this
+ License. If You create a Collection, upon notice from any Licensor You
+ must, to the extent practicable, remove from the Collection any credit
+ as required by Section 4(c), as requested. If You create an
+ Adaptation, upon notice from any Licensor You must, to the extent
+ practicable, remove from the Adaptation any credit as required by
+ Section 4(c), as requested.
+ b. You may Distribute or Publicly Perform an Adaptation only under the
+ terms of: (i) this License; (ii) a later version of this License with
+ the same License Elements as this License; (iii) a Creative Commons
+ jurisdiction license (either this or a later license version) that
+ contains the same License Elements as this License (e.g.,
+ Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible
+ License. If you license the Adaptation under one of the licenses
+ mentioned in (iv), you must comply with the terms of that license. If
+ you license the Adaptation under the terms of any of the licenses
+ mentioned in (i), (ii) or (iii) (the "Applicable License"), you must
+ comply with the terms of the Applicable License generally and the
+ following provisions: (I) You must include a copy of, or the URI for,
+ the Applicable License with every copy of each Adaptation You
+ Distribute or Publicly Perform; (II) You may not offer or impose any
+ terms on the Adaptation that restrict the terms of the Applicable
+ License or the ability of the recipient of the Adaptation to exercise
+ the rights granted to that recipient under the terms of the Applicable
+ License; (III) You must keep intact all notices that refer to the
+ Applicable License and to the disclaimer of warranties with every copy
+ of the Work as included in the Adaptation You Distribute or Publicly
+ Perform; (IV) when You Distribute or Publicly Perform the Adaptation,
+ You may not impose any effective technological measures on the
+ Adaptation that restrict the ability of a recipient of the Adaptation
+ from You to exercise the rights granted to that recipient under the
+ terms of the Applicable License. This Section 4(b) applies to the
+ Adaptation as incorporated in a Collection, but this does not require
+ the Collection apart from the Adaptation itself to be made subject to
+ the terms of the Applicable License.
+ c. If You Distribute, or Publicly Perform the Work or any Adaptations or
+ Collections, You must, unless a request has been made pursuant to
+ Section 4(a), keep intact all copyright notices for the Work and
+ provide, reasonable to the medium or means You are utilizing: (i) the
+ name of the Original Author (or pseudonym, if applicable) if supplied,
+ and/or if the Original Author and/or Licensor designate another party
+ or parties (e.g., a sponsor institute, publishing entity, journal) for
+ attribution ("Attribution Parties") in Licensor's copyright notice,
+ terms of service or by other reasonable means, the name of such party
+ or parties; (ii) the title of the Work if supplied; (iii) to the
+ extent reasonably practicable, the URI, if any, that Licensor
+ specifies to be associated with the Work, unless such URI does not
+ refer to the copyright notice or licensing information for the Work;
+ and (iv) , consistent with Ssection 3(b), in the case of an
+ Adaptation, a credit identifying the use of the Work in the Adaptation
+ (e.g., "French translation of the Work by Original Author," or
+ "Screenplay based on original Work by Original Author"). The credit
+ required by this Section 4(c) may be implemented in any reasonable
+ manner; provided, however, that in the case of a Adaptation or
+ Collection, at a minimum such credit will appear, if a credit for all
+ contributing authors of the Adaptation or Collection appears, then as
+ part of these credits and in a manner at least as prominent as the
+ credits for the other contributing authors. For the avoidance of
+ doubt, You may only use the credit required by this Section for the
+ purpose of attribution in the manner set out above and, by exercising
+ Your rights under this License, You may not implicitly or explicitly
+ assert or imply any connection with, sponsorship or endorsement by the
+ Original Author, Licensor and/or Attribution Parties, as appropriate,
+ of You or Your use of the Work, without the separate, express prior
+ written permission of the Original Author, Licensor and/or Attribution
+ Parties.
+ d. Except as otherwise agreed in writing by the Licensor or as may be
+ otherwise permitted by applicable law, if You Reproduce, Distribute or
+ Publicly Perform the Work either by itself or as part of any
+ Adaptations or Collections, You must not distort, mutilate, modify or
+ take other derogatory action in relation to the Work which would be
+ prejudicial to the Original Author's honor or reputation. Licensor
+ agrees that in those jurisdictions (e.g. Japan), in which any exercise
+ of the right granted in Section 3(b) of this License (the right to
+ make Adaptations) would be deemed to be a distortion, mutilation,
+ modification or other derogatory action prejudicial to the Original
+ Author's honor and reputation, the Licensor will waive or not assert,
+ as appropriate, this Section, to the fullest extent permitted by the
+ applicable national law, to enable You to reasonably exercise Your
+ right under Section 3(b) of this License (right to make Adaptations)
+ but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+ automatically upon any breach by You of the terms of this License.
+ Individuals or entities who have received Adaptations or Collections
+ from You under this License, however, will not have their licenses
+ terminated provided such individuals or entities remain in full
+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+ survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+ perpetual (for the duration of the applicable copyright in the Work).
+ Notwithstanding the above, Licensor reserves the right to release the
+ Work under different license terms or to stop distributing the Work at
+ any time; provided, however that any such election will not serve to
+ withdraw this License (or any other license that has been, or is
+ required to be, granted under the terms of this License), and this
+ License will continue in full force and effect unless terminated as
+ stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+ the Licensor offers to the recipient a license to the Work on the same
+ terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+ offers to the recipient a license to the original Work on the same
+ terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this License, and without further action
+ by the parties to this agreement, such provision shall be reformed to
+ the minimum extent necessary to make such provision valid and
+ enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+ breach consented to unless such waiver or consent shall be in writing
+ and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+ respect to the Work licensed here. There are no understandings,
+ agreements or representations with respect to the Work not specified
+ here. Licensor shall not be bound by any additional provisions that
+ may appear in any communication from You. This License may not be
+ modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+ License were drafted utilizing the terminology of the Berne Convention
+ for the Protection of Literary and Artistic Works (as amended on
+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+ and the Universal Copyright Convention (as revised on July 24, 1971).
+ These rights and subject matter take effect in the relevant
+ jurisdiction in which the License terms are sought to be enforced
+ according to the corresponding provisions of the implementation of
+ those treaty provisions in the applicable national law. If the
+ standard suite of rights granted under applicable copyright law
+ includes additional rights not granted under this License, such
+ additional rights are deemed to be included in the License; this
+ License is not intended to restrict the license of any rights under
+ applicable law.
+
+
+Creative Commons Notice
+
+ Creative Commons is not a party to this License, and makes no warranty
+ whatsoever in connection with the Work. Creative Commons will not be
+ liable to You or any party on any legal theory for any damages
+ whatsoever, including without limitation any general, special,
+ incidental or consequential damages arising in connection to this
+ license. Notwithstanding the foregoing two (2) sentences, if Creative
+ Commons has expressly identified itself as the Licensor hereunder, it
+ shall have all rights and obligations of Licensor.
+
+ Except for the limited purpose of indicating to the public that the
+ Work is licensed under the CCPL, Creative Commons does not authorize
+ the use by either party of the trademark "Creative Commons" or any
+ related trademark or logo of Creative Commons without the prior
+ written consent of Creative Commons. Any permitted use will be in
+ compliance with Creative Commons' then-current trademark usage
+ guidelines, as may be published on its website or otherwise made
+ available upon request from time to time. For the avoidance of doubt,
+ this trademark restriction does not form part of the License.
+
+ Creative Commons may be contacted at https://creativecommons.org/.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/README.txt b/testing/web-platform/mozilla/tests/indic-detection/README.txt
new file mode 100644
index 0000000000..9fa13a660a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/README.txt
@@ -0,0 +1,14 @@
+The text (non-markup/JavaScript) content of the files in this directory originates from Wikipedia and
+is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported license
+<https://creativecommons.org/licenses/by-sa/3.0/legalcode>.
+
+The content comes from the following articles (and their revisions):
+https://hi.wikipedia.org/w/index.php?title=%E0%A4%AE%E0%A4%82%E0%A4%97%E0%A4%B2_%E0%A4%97%E0%A5%8D%E0%A4%B0%E0%A4%B9&oldid=5105576
+https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711
+
+This directory tests that content meant for intentionally mis-encoded legacy Devanagari and Tamil fonts that Chrome's encoding detector knows about is detected as windows-1252. These fonts assign Devanagari or Tamil glyphs to code points that are symbols or Latin characters in windows-1252. In chardetng, the detection mechanism is determining that the content isn't in any chardetng-supported encoding and, therefore, the fallback is windows-1252.
+
+Tests are missing for the following fonts that Chrome knows about:
+LT TM Barani
+TMNews
+TamilWeb
diff --git a/testing/web-platform/mozilla/tests/indic-detection/baskar-jagran.html b/testing/web-platform/mozilla/tests/indic-detection/baskar-jagran.html
new file mode 100644
index 0000000000..c8de3ec2a4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/baskar-jagran.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ע ע UUU UUU Q , " " UUU ע UUU UUU - "S " ٷUUU
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://hi.wikipedia.org/w/index.php?title=%E0%A4%AE%E0%A4%82%E0%A4%97%E0%A4%B2_%E0%A4%97%E0%A5%8D%E0%A4%B0%E0%A4%B9&oldid=5105576">&#2350;&#2306;&#2327;&#2354; &#2327;&#2381;&#2352;&#2361;</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/elango.html b/testing/web-platform/mozilla/tests/indic-detection/elango.html
new file mode 100644
index 0000000000..175917cfd8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/elango.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+NYY֚ (Mars) sVeh|T E[ J Lַ Bh. C sV]X죋 SLY L[L E[.Ceh|T LopV L[] Reh A|RRL CWQPY pV L[L NYY֚ Cef\. U]yz] CeLֺeh T֟eLP TVWo syz[]. CR UTWT둥 LQTT| C BeN| CeL[o NS\ULe Ly|f\.[12] CR]XV CRho NYY֚ G\ TV HTyP. J N֟ L[] CR UTWT NW] E[T֥ fQQe hZL[, E[ T\ GUXL, T[RehL, TXY]jL, T]zV YT ThL[ LQP. NYY֛ rZpeLX, TY Uּ\jL eh E[RT T\YV. sV UQPX L EVWU] JXTr UX, LTTV NjhT T[RehL J\] U] T[Reh NYY֛XV E[].
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/htchanakya.html b/testing/web-platform/mozilla/tests/indic-detection/htchanakya.html
new file mode 100644
index 0000000000..27c1ce5510
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/htchanakya.html
@@ -0,0 +1,12 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+״ U״ XW XW UQ , " " XW U״ XW U XW - "S " XW U " " XWU f XW U, ״ XW S U XW UJ U XW U XW U f XW , , US U VLW YW XW U״ XW XW W , ܳ i ״ U S XWi UU U S XW XW , ״ XW J XW U XW f XW U XW XW UXW XW
+
+v~{z UU y XW mU XW ״ XW XW XW U U S XW XW U U U XW Ϧ XW XW U U U U, VLW , ܴ U U m XW U ι , XW striations XW G XWU XW mU XW ⴿ U XW MW XW U XW λ h U XW U XW XW XWU U YWU , U ״ XW f XW , ״ XW SU XW PJ XW
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://hi.wikipedia.org/w/index.php?title=%E0%A4%AE%E0%A4%82%E0%A4%97%E0%A4%B2_%E0%A4%97%E0%A5%8D%E0%A4%B0%E0%A4%B9&oldid=5105576">&#2350;&#2306;&#2327;&#2354; &#2327;&#2381;&#2352;&#2361;</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/shreetam.html b/testing/web-platform/mozilla/tests/indic-detection/shreetam.html
new file mode 100644
index 0000000000..1fcf4ae40f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/shreetam.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+\ (Mars) `USkzv E J P BS. Cx `ۼx |Px PP Ex.CUSkzv Pa]ԯ P uUS AkzuuP Cshx ]ԯ PP \ CUQx. miں CUPUS UPh a `miں. Cu أ Pnk C BU\k CUPa \{өPU PmkQx.[12] Cu CuSa \ G Hأmhx. J \ P Cu أ \v Ex QsnU SPͲ, ° Ex GP, zuUSP, [P, ۉi x SvPͲ Pshx. \ _]UP, [PЮ US Eu . ` shzx P E J_ , P \[Szx zuUSP J ں zuUS \ E.
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/tab.html b/testing/web-platform/mozilla/tests/indic-detection/tab.html
new file mode 100644
index 0000000000..1dc5ee85bc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/tab.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ (Mars) 袰 ݰ. ޶  .袰 袰 ܴ ޼. 좮 被袰 좮. ޼ 袬 被裬 좴.[12] . , , 袰, , ͮ . , 袰 .  , 颰 袰 袰 .
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/tam.html b/testing/web-platform/mozilla/tests/indic-detection/tam.html
new file mode 100644
index 0000000000..8b4f9d0cbf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/tam.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ (Mars) K򂰴F 補 ݰ. ޶ KQL  .ނF ICP ‚ ܴ CP ޼A. ނ 𣘂O ņ. H ޼ ݂ ނ裬 G 裆A.[12]  . M꣘ FQ A N, MJ K, , , Qͮ F 裇. J C, M . K 􈶜 I L , I芪K ꃰ  K  J .
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/tboomi.html b/testing/web-platform/mozilla/tests/indic-detection/tboomi.html
new file mode 100644
index 0000000000..3976416449
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/tboomi.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+%NY (Mars) wVfjiT E[ J &L Bj. C wVë SLY &L[L E[.CfjiT LotV &L[] Rfj AiRRL CWPY tV &L[L %NY Cfg\. &U]}~] Cf&Lfj &TfLP %TV+Wo w}~[]. CR &UTW LQTi Cö Bf+Ni Cf&L+[o %N\ULf L}ig\.[12] CR]&X&V CRjo %NY G\ %TV HT}P. J N &L[] CR &UTW NW E[&T gQf jL+[, ˼ E[ &T\ GU+XL, T[RfjL, T+XY]lL, T~V Y TjL+[ %LP. %NY vZtfLX, TY U\lLض fj E[+R &T\+Y&V. wV UPX L EVWU] JƶTv U+X, L%TV %Nlj T[RfjL J\] U] T[Rfj %NY&X&V E[].
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/indic-detection/tscii.html b/testing/web-platform/mozilla/tests/indic-detection/tscii.html
new file mode 100644
index 0000000000..c9d47b4f9f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/indic-detection/tscii.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+š (Mars) â . âɢĢ ǡ . Ȣ ǡ Ҿ 򾾡 Ȣ ǡ š 츢. ɡ 째 츼Ǣ ¨ . 쨺 째 θ.[12] ɡħ š . Ţ ǡ ɢ Ч Ƣ, Ţ¢ âĸ, ̸, , ɢ ̾ . š¢ 측, Ţ Ǩ Ȩŧ. â Ģ , â ̸ ȡ â š¢ħ .
+<script>
+test(function() {
+ assert_equals(document.characterSet, "windows-1252");
+},"Should fall back to windows-1252");
+</script>
+The text content above is a converted extract from the start of the Wikipedia article <a href="https://ta.wikipedia.org/w/index.php?title=%E0%AE%9A%E0%AF%86%E0%AE%B5%E0%AF%8D%E0%AE%B5%E0%AE%BE%E0%AE%AF%E0%AF%8D_(%E0%AE%95%E0%AF%8B%E0%AE%B3%E0%AF%8D)&oldid=3129711">&#2970;&#3014;&#2997;&#3021;&#2997;&#3006;&#2991;&#3021; (&#2965;&#3019;&#2995;&#3021;)</a> and
+is licensed under the <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode">Creative Commons Attribution-ShareAlike 3.0 Unported</a> license.
diff --git a/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-0.html b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-0.html
new file mode 100644
index 0000000000..584620392c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-0.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<link rel="match" href="prefs-false.html"/>
+<div id="result"></div>
+<script>
+// This can be any pref, as long as it doesn't affect the test and the default value is false
+// If it's updated here prefs-1.html and prefs-2.html need the same update
+result.innerHTML = SpecialPowers.getBoolPref("apz.allow_zooming_out");
+document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-1.html b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-1.html
new file mode 100644
index 0000000000..8f1029d3ff
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<link rel="match" href="prefs-true.html"/>
+<div id="result"></div>
+<script>
+// If the pref is changed here, it needs to also be changed in the corresponding ini file
+result.innerHTML = SpecialPowers.getBoolPref("apz.allow_zooming_out");
+document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-2.html b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-2.html
new file mode 100644
index 0000000000..54ebde2ebe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<link rel="match" href="prefs-false.html"/>
+<div id="result"></div>
+<script>
+result.innerHTML = SpecialPowers.getBoolPref("apz.allow_zooming_out");
+document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-false.html b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-false.html
new file mode 100644
index 0000000000..667d1e1bf6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-false.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<div id="result">false</div>
+</html>
diff --git a/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-true.html b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-true.html
new file mode 100644
index 0000000000..df3fe20eff
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/prefs/prefs-true.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<div id="result">true</div>
+</html>
diff --git a/testing/web-platform/mozilla/tests/infrastructure/specialPowers/specialpowers.html b/testing/web-platform/mozilla/tests/infrastructure/specialPowers/specialpowers.html
new file mode 100644
index 0000000000..38615028d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/infrastructure/specialPowers/specialpowers.html
@@ -0,0 +1,7 @@
+<title>Check specialPowers is available in gecko-only tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+test(() => assert_equals(SpecialPowers.sanityCheck(), "foo"))
+</script>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font-ref.html
new file mode 100644
index 0000000000..6ebfd75c2f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Basic mathvariant transforms with the default font (reference)</title>
+ </head>
+ <body>
+ <p>Test passes if you see three lines of text rendered with corresponding
+ italic, bold, bold-italic characters from the
+ Mathematical Alphanumeric Symbols block:</p>
+ <p><math><mtext>𝐼𝑡𝑎𝑙𝑖𝑐</mtext></math></p>
+ <p><math><mtext>𝐁𝐨𝐥𝐝</mtext></math></p>
+ <p><math><mtext>𝑩𝒐𝒍𝒅𝑰𝒕𝒂𝒍𝒊𝒄</mtext></math></p>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html
new file mode 100644
index 0000000000..24c868c495
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-basic-transforms-with-default-font.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Basic mathvariant transforms with the default font</title>
+ <link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1789083">
+ <link rel="match" href="mathvariant-basic-transforms-with-default-font-ref.html"/>
+ <meta name="assert" content="Verify that the default font provides Mathematical Alphanumeric Symbols to perform basic mathvariant transforms (italic, bold, bold-italic), without requiring some kind of style fallback.">
+ </head>
+ <body>
+ <p>Test passes if you see three lines of text rendered with corresponding
+ italic, bold, bold-italic characters from the
+ Mathematical Alphanumeric Symbols block:</p>
+ <p><math><mtext mathvariant="italic">Italic</mtext></math></p>
+ <p><math><mtext mathvariant="bold">Bold</mtext></math></p>
+ <p><math><mtext mathvariant="bold-italic">BoldItalic</mtext></math></p>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur-ref.html
new file mode 100644
index 0000000000..44588948e7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-fraktur (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D56C;</mtext></math>=<span>1D56C</span></span>
+ <span><math class="testfont"><mtext>&#x1D56D;</mtext></math>=<span>1D56D</span></span>
+ <span><math class="testfont"><mtext>&#x1D56E;</mtext></math>=<span>1D56E</span></span>
+ <span><math class="testfont"><mtext>&#x1D56F;</mtext></math>=<span>1D56F</span></span>
+ <span><math class="testfont"><mtext>&#x1D570;</mtext></math>=<span>1D570</span></span>
+ <span><math class="testfont"><mtext>&#x1D571;</mtext></math>=<span>1D571</span></span>
+ <span><math class="testfont"><mtext>&#x1D572;</mtext></math>=<span>1D572</span></span>
+ <span><math class="testfont"><mtext>&#x1D573;</mtext></math>=<span>1D573</span></span>
+ <span><math class="testfont"><mtext>&#x1D574;</mtext></math>=<span>1D574</span></span>
+ <span><math class="testfont"><mtext>&#x1D575;</mtext></math>=<span>1D575</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D576;</mtext></math>=<span>1D576</span></span>
+ <span><math class="testfont"><mtext>&#x1D577;</mtext></math>=<span>1D577</span></span>
+ <span><math class="testfont"><mtext>&#x1D578;</mtext></math>=<span>1D578</span></span>
+ <span><math class="testfont"><mtext>&#x1D579;</mtext></math>=<span>1D579</span></span>
+ <span><math class="testfont"><mtext>&#x1D57A;</mtext></math>=<span>1D57A</span></span>
+ <span><math class="testfont"><mtext>&#x1D57B;</mtext></math>=<span>1D57B</span></span>
+ <span><math class="testfont"><mtext>&#x1D57C;</mtext></math>=<span>1D57C</span></span>
+ <span><math class="testfont"><mtext>&#x1D57D;</mtext></math>=<span>1D57D</span></span>
+ <span><math class="testfont"><mtext>&#x1D57E;</mtext></math>=<span>1D57E</span></span>
+ <span><math class="testfont"><mtext>&#x1D57F;</mtext></math>=<span>1D57F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D580;</mtext></math>=<span>1D580</span></span>
+ <span><math class="testfont"><mtext>&#x1D581;</mtext></math>=<span>1D581</span></span>
+ <span><math class="testfont"><mtext>&#x1D582;</mtext></math>=<span>1D582</span></span>
+ <span><math class="testfont"><mtext>&#x1D583;</mtext></math>=<span>1D583</span></span>
+ <span><math class="testfont"><mtext>&#x1D584;</mtext></math>=<span>1D584</span></span>
+ <span><math class="testfont"><mtext>&#x1D585;</mtext></math>=<span>1D585</span></span>
+ <span><math class="testfont"><mtext>&#x1D586;</mtext></math>=<span>1D586</span></span>
+ <span><math class="testfont"><mtext>&#x1D587;</mtext></math>=<span>1D587</span></span>
+ <span><math class="testfont"><mtext>&#x1D588;</mtext></math>=<span>1D588</span></span>
+ <span><math class="testfont"><mtext>&#x1D589;</mtext></math>=<span>1D589</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D58A;</mtext></math>=<span>1D58A</span></span>
+ <span><math class="testfont"><mtext>&#x1D58B;</mtext></math>=<span>1D58B</span></span>
+ <span><math class="testfont"><mtext>&#x1D58C;</mtext></math>=<span>1D58C</span></span>
+ <span><math class="testfont"><mtext>&#x1D58D;</mtext></math>=<span>1D58D</span></span>
+ <span><math class="testfont"><mtext>&#x1D58E;</mtext></math>=<span>1D58E</span></span>
+ <span><math class="testfont"><mtext>&#x1D58F;</mtext></math>=<span>1D58F</span></span>
+ <span><math class="testfont"><mtext>&#x1D590;</mtext></math>=<span>1D590</span></span>
+ <span><math class="testfont"><mtext>&#x1D591;</mtext></math>=<span>1D591</span></span>
+ <span><math class="testfont"><mtext>&#x1D592;</mtext></math>=<span>1D592</span></span>
+ <span><math class="testfont"><mtext>&#x1D593;</mtext></math>=<span>1D593</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D594;</mtext></math>=<span>1D594</span></span>
+ <span><math class="testfont"><mtext>&#x1D595;</mtext></math>=<span>1D595</span></span>
+ <span><math class="testfont"><mtext>&#x1D596;</mtext></math>=<span>1D596</span></span>
+ <span><math class="testfont"><mtext>&#x1D597;</mtext></math>=<span>1D597</span></span>
+ <span><math class="testfont"><mtext>&#x1D598;</mtext></math>=<span>1D598</span></span>
+ <span><math class="testfont"><mtext>&#x1D599;</mtext></math>=<span>1D599</span></span>
+ <span><math class="testfont"><mtext>&#x1D59A;</mtext></math>=<span>1D59A</span></span>
+ <span><math class="testfont"><mtext>&#x1D59B;</mtext></math>=<span>1D59B</span></span>
+ <span><math class="testfont"><mtext>&#x1D59C;</mtext></math>=<span>1D59C</span></span>
+ <span><math class="testfont"><mtext>&#x1D59D;</mtext></math>=<span>1D59D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D59E;</mtext></math>=<span>1D59E</span></span>
+ <span><math class="testfont"><mtext>&#x1D59F;</mtext></math>=<span>1D59F</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur.html
new file mode 100644
index 0000000000..32d037603b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-fraktur.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-fraktur</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#bold-fraktur-mappings">
+<link rel="match" href="mathvariant-bold-fraktur-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-fraktur mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x41;</mtext></math>=<span>1D56C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x42;</mtext></math>=<span>1D56D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x43;</mtext></math>=<span>1D56E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x44;</mtext></math>=<span>1D56F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x45;</mtext></math>=<span>1D570</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x46;</mtext></math>=<span>1D571</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x47;</mtext></math>=<span>1D572</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x48;</mtext></math>=<span>1D573</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x49;</mtext></math>=<span>1D574</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4A;</mtext></math>=<span>1D575</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4B;</mtext></math>=<span>1D576</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4C;</mtext></math>=<span>1D577</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4D;</mtext></math>=<span>1D578</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4E;</mtext></math>=<span>1D579</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x4F;</mtext></math>=<span>1D57A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x50;</mtext></math>=<span>1D57B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x51;</mtext></math>=<span>1D57C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x52;</mtext></math>=<span>1D57D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x53;</mtext></math>=<span>1D57E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x54;</mtext></math>=<span>1D57F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x55;</mtext></math>=<span>1D580</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x56;</mtext></math>=<span>1D581</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x57;</mtext></math>=<span>1D582</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x58;</mtext></math>=<span>1D583</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x59;</mtext></math>=<span>1D584</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x5A;</mtext></math>=<span>1D585</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x61;</mtext></math>=<span>1D586</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x62;</mtext></math>=<span>1D587</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x63;</mtext></math>=<span>1D588</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x64;</mtext></math>=<span>1D589</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x65;</mtext></math>=<span>1D58A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x66;</mtext></math>=<span>1D58B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x67;</mtext></math>=<span>1D58C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x68;</mtext></math>=<span>1D58D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x69;</mtext></math>=<span>1D58E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6A;</mtext></math>=<span>1D58F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6B;</mtext></math>=<span>1D590</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6C;</mtext></math>=<span>1D591</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6D;</mtext></math>=<span>1D592</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6E;</mtext></math>=<span>1D593</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x6F;</mtext></math>=<span>1D594</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x70;</mtext></math>=<span>1D595</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x71;</mtext></math>=<span>1D596</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x72;</mtext></math>=<span>1D597</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x73;</mtext></math>=<span>1D598</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x74;</mtext></math>=<span>1D599</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x75;</mtext></math>=<span>1D59A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x76;</mtext></math>=<span>1D59B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x77;</mtext></math>=<span>1D59C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x78;</mtext></math>=<span>1D59D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x79;</mtext></math>=<span>1D59E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-fraktur">&#x7A;</mtext></math>=<span>1D59F</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic-ref.html
new file mode 100644
index 0000000000..9a93a37e35
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic-ref.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-italic (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D468;</mtext></math>=<span>1D468</span></span>
+ <span><math class="testfont"><mtext>&#x1D469;</mtext></math>=<span>1D469</span></span>
+ <span><math class="testfont"><mtext>&#x1D46A;</mtext></math>=<span>1D46A</span></span>
+ <span><math class="testfont"><mtext>&#x1D46B;</mtext></math>=<span>1D46B</span></span>
+ <span><math class="testfont"><mtext>&#x1D46C;</mtext></math>=<span>1D46C</span></span>
+ <span><math class="testfont"><mtext>&#x1D46D;</mtext></math>=<span>1D46D</span></span>
+ <span><math class="testfont"><mtext>&#x1D46E;</mtext></math>=<span>1D46E</span></span>
+ <span><math class="testfont"><mtext>&#x1D46F;</mtext></math>=<span>1D46F</span></span>
+ <span><math class="testfont"><mtext>&#x1D470;</mtext></math>=<span>1D470</span></span>
+ <span><math class="testfont"><mtext>&#x1D471;</mtext></math>=<span>1D471</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D472;</mtext></math>=<span>1D472</span></span>
+ <span><math class="testfont"><mtext>&#x1D473;</mtext></math>=<span>1D473</span></span>
+ <span><math class="testfont"><mtext>&#x1D474;</mtext></math>=<span>1D474</span></span>
+ <span><math class="testfont"><mtext>&#x1D475;</mtext></math>=<span>1D475</span></span>
+ <span><math class="testfont"><mtext>&#x1D476;</mtext></math>=<span>1D476</span></span>
+ <span><math class="testfont"><mtext>&#x1D477;</mtext></math>=<span>1D477</span></span>
+ <span><math class="testfont"><mtext>&#x1D478;</mtext></math>=<span>1D478</span></span>
+ <span><math class="testfont"><mtext>&#x1D479;</mtext></math>=<span>1D479</span></span>
+ <span><math class="testfont"><mtext>&#x1D47A;</mtext></math>=<span>1D47A</span></span>
+ <span><math class="testfont"><mtext>&#x1D47B;</mtext></math>=<span>1D47B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D47C;</mtext></math>=<span>1D47C</span></span>
+ <span><math class="testfont"><mtext>&#x1D47D;</mtext></math>=<span>1D47D</span></span>
+ <span><math class="testfont"><mtext>&#x1D47E;</mtext></math>=<span>1D47E</span></span>
+ <span><math class="testfont"><mtext>&#x1D47F;</mtext></math>=<span>1D47F</span></span>
+ <span><math class="testfont"><mtext>&#x1D480;</mtext></math>=<span>1D480</span></span>
+ <span><math class="testfont"><mtext>&#x1D481;</mtext></math>=<span>1D481</span></span>
+ <span><math class="testfont"><mtext>&#x1D482;</mtext></math>=<span>1D482</span></span>
+ <span><math class="testfont"><mtext>&#x1D483;</mtext></math>=<span>1D483</span></span>
+ <span><math class="testfont"><mtext>&#x1D484;</mtext></math>=<span>1D484</span></span>
+ <span><math class="testfont"><mtext>&#x1D485;</mtext></math>=<span>1D485</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D486;</mtext></math>=<span>1D486</span></span>
+ <span><math class="testfont"><mtext>&#x1D487;</mtext></math>=<span>1D487</span></span>
+ <span><math class="testfont"><mtext>&#x1D488;</mtext></math>=<span>1D488</span></span>
+ <span><math class="testfont"><mtext>&#x1D489;</mtext></math>=<span>1D489</span></span>
+ <span><math class="testfont"><mtext>&#x1D48A;</mtext></math>=<span>1D48A</span></span>
+ <span><math class="testfont"><mtext>&#x1D48B;</mtext></math>=<span>1D48B</span></span>
+ <span><math class="testfont"><mtext>&#x1D48C;</mtext></math>=<span>1D48C</span></span>
+ <span><math class="testfont"><mtext>&#x1D48D;</mtext></math>=<span>1D48D</span></span>
+ <span><math class="testfont"><mtext>&#x1D48E;</mtext></math>=<span>1D48E</span></span>
+ <span><math class="testfont"><mtext>&#x1D48F;</mtext></math>=<span>1D48F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D490;</mtext></math>=<span>1D490</span></span>
+ <span><math class="testfont"><mtext>&#x1D491;</mtext></math>=<span>1D491</span></span>
+ <span><math class="testfont"><mtext>&#x1D492;</mtext></math>=<span>1D492</span></span>
+ <span><math class="testfont"><mtext>&#x1D493;</mtext></math>=<span>1D493</span></span>
+ <span><math class="testfont"><mtext>&#x1D494;</mtext></math>=<span>1D494</span></span>
+ <span><math class="testfont"><mtext>&#x1D495;</mtext></math>=<span>1D495</span></span>
+ <span><math class="testfont"><mtext>&#x1D496;</mtext></math>=<span>1D496</span></span>
+ <span><math class="testfont"><mtext>&#x1D497;</mtext></math>=<span>1D497</span></span>
+ <span><math class="testfont"><mtext>&#x1D498;</mtext></math>=<span>1D498</span></span>
+ <span><math class="testfont"><mtext>&#x1D499;</mtext></math>=<span>1D499</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D49A;</mtext></math>=<span>1D49A</span></span>
+ <span><math class="testfont"><mtext>&#x1D49B;</mtext></math>=<span>1D49B</span></span>
+ <span><math class="testfont"><mtext>&#x1D71C;</mtext></math>=<span>1D71C</span></span>
+ <span><math class="testfont"><mtext>&#x1D71D;</mtext></math>=<span>1D71D</span></span>
+ <span><math class="testfont"><mtext>&#x1D71E;</mtext></math>=<span>1D71E</span></span>
+ <span><math class="testfont"><mtext>&#x1D71F;</mtext></math>=<span>1D71F</span></span>
+ <span><math class="testfont"><mtext>&#x1D720;</mtext></math>=<span>1D720</span></span>
+ <span><math class="testfont"><mtext>&#x1D721;</mtext></math>=<span>1D721</span></span>
+ <span><math class="testfont"><mtext>&#x1D722;</mtext></math>=<span>1D722</span></span>
+ <span><math class="testfont"><mtext>&#x1D723;</mtext></math>=<span>1D723</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D724;</mtext></math>=<span>1D724</span></span>
+ <span><math class="testfont"><mtext>&#x1D725;</mtext></math>=<span>1D725</span></span>
+ <span><math class="testfont"><mtext>&#x1D726;</mtext></math>=<span>1D726</span></span>
+ <span><math class="testfont"><mtext>&#x1D727;</mtext></math>=<span>1D727</span></span>
+ <span><math class="testfont"><mtext>&#x1D728;</mtext></math>=<span>1D728</span></span>
+ <span><math class="testfont"><mtext>&#x1D729;</mtext></math>=<span>1D729</span></span>
+ <span><math class="testfont"><mtext>&#x1D72A;</mtext></math>=<span>1D72A</span></span>
+ <span><math class="testfont"><mtext>&#x1D72B;</mtext></math>=<span>1D72B</span></span>
+ <span><math class="testfont"><mtext>&#x1D72C;</mtext></math>=<span>1D72C</span></span>
+ <span><math class="testfont"><mtext>&#x1D72D;</mtext></math>=<span>1D72D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D72E;</mtext></math>=<span>1D72E</span></span>
+ <span><math class="testfont"><mtext>&#x1D72F;</mtext></math>=<span>1D72F</span></span>
+ <span><math class="testfont"><mtext>&#x1D730;</mtext></math>=<span>1D730</span></span>
+ <span><math class="testfont"><mtext>&#x1D731;</mtext></math>=<span>1D731</span></span>
+ <span><math class="testfont"><mtext>&#x1D732;</mtext></math>=<span>1D732</span></span>
+ <span><math class="testfont"><mtext>&#x1D733;</mtext></math>=<span>1D733</span></span>
+ <span><math class="testfont"><mtext>&#x1D734;</mtext></math>=<span>1D734</span></span>
+ <span><math class="testfont"><mtext>&#x1D735;</mtext></math>=<span>1D735</span></span>
+ <span><math class="testfont"><mtext>&#x1D736;</mtext></math>=<span>1D736</span></span>
+ <span><math class="testfont"><mtext>&#x1D737;</mtext></math>=<span>1D737</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D738;</mtext></math>=<span>1D738</span></span>
+ <span><math class="testfont"><mtext>&#x1D739;</mtext></math>=<span>1D739</span></span>
+ <span><math class="testfont"><mtext>&#x1D73A;</mtext></math>=<span>1D73A</span></span>
+ <span><math class="testfont"><mtext>&#x1D73B;</mtext></math>=<span>1D73B</span></span>
+ <span><math class="testfont"><mtext>&#x1D73C;</mtext></math>=<span>1D73C</span></span>
+ <span><math class="testfont"><mtext>&#x1D73D;</mtext></math>=<span>1D73D</span></span>
+ <span><math class="testfont"><mtext>&#x1D73E;</mtext></math>=<span>1D73E</span></span>
+ <span><math class="testfont"><mtext>&#x1D73F;</mtext></math>=<span>1D73F</span></span>
+ <span><math class="testfont"><mtext>&#x1D740;</mtext></math>=<span>1D740</span></span>
+ <span><math class="testfont"><mtext>&#x1D741;</mtext></math>=<span>1D741</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D742;</mtext></math>=<span>1D742</span></span>
+ <span><math class="testfont"><mtext>&#x1D743;</mtext></math>=<span>1D743</span></span>
+ <span><math class="testfont"><mtext>&#x1D744;</mtext></math>=<span>1D744</span></span>
+ <span><math class="testfont"><mtext>&#x1D745;</mtext></math>=<span>1D745</span></span>
+ <span><math class="testfont"><mtext>&#x1D746;</mtext></math>=<span>1D746</span></span>
+ <span><math class="testfont"><mtext>&#x1D747;</mtext></math>=<span>1D747</span></span>
+ <span><math class="testfont"><mtext>&#x1D748;</mtext></math>=<span>1D748</span></span>
+ <span><math class="testfont"><mtext>&#x1D749;</mtext></math>=<span>1D749</span></span>
+ <span><math class="testfont"><mtext>&#x1D74A;</mtext></math>=<span>1D74A</span></span>
+ <span><math class="testfont"><mtext>&#x1D74B;</mtext></math>=<span>1D74B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D74C;</mtext></math>=<span>1D74C</span></span>
+ <span><math class="testfont"><mtext>&#x1D74D;</mtext></math>=<span>1D74D</span></span>
+ <span><math class="testfont"><mtext>&#x1D74E;</mtext></math>=<span>1D74E</span></span>
+ <span><math class="testfont"><mtext>&#x1D74F;</mtext></math>=<span>1D74F</span></span>
+ <span><math class="testfont"><mtext>&#x1D750;</mtext></math>=<span>1D750</span></span>
+ <span><math class="testfont"><mtext>&#x1D751;</mtext></math>=<span>1D751</span></span>
+ <span><math class="testfont"><mtext>&#x1D752;</mtext></math>=<span>1D752</span></span>
+ <span><math class="testfont"><mtext>&#x1D753;</mtext></math>=<span>1D753</span></span>
+ <span><math class="testfont"><mtext>&#x1D754;</mtext></math>=<span>1D754</span></span>
+ <span><math class="testfont"><mtext>&#x1D755;</mtext></math>=<span>1D755</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic.html
new file mode 100644
index 0000000000..725559a571
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-italic.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-italic</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#bold-italic-mappings">
+<link rel="match" href="mathvariant-bold-italic-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x41;</mtext></math>=<span>1D468</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x42;</mtext></math>=<span>1D469</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x43;</mtext></math>=<span>1D46A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x44;</mtext></math>=<span>1D46B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x45;</mtext></math>=<span>1D46C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x46;</mtext></math>=<span>1D46D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x47;</mtext></math>=<span>1D46E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x48;</mtext></math>=<span>1D46F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x49;</mtext></math>=<span>1D470</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4A;</mtext></math>=<span>1D471</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4B;</mtext></math>=<span>1D472</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4C;</mtext></math>=<span>1D473</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4D;</mtext></math>=<span>1D474</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4E;</mtext></math>=<span>1D475</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x4F;</mtext></math>=<span>1D476</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x50;</mtext></math>=<span>1D477</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x51;</mtext></math>=<span>1D478</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x52;</mtext></math>=<span>1D479</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x53;</mtext></math>=<span>1D47A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x54;</mtext></math>=<span>1D47B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x55;</mtext></math>=<span>1D47C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x56;</mtext></math>=<span>1D47D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x57;</mtext></math>=<span>1D47E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x58;</mtext></math>=<span>1D47F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x59;</mtext></math>=<span>1D480</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x5A;</mtext></math>=<span>1D481</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x61;</mtext></math>=<span>1D482</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x62;</mtext></math>=<span>1D483</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x63;</mtext></math>=<span>1D484</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x64;</mtext></math>=<span>1D485</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x65;</mtext></math>=<span>1D486</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x66;</mtext></math>=<span>1D487</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x67;</mtext></math>=<span>1D488</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x68;</mtext></math>=<span>1D489</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x69;</mtext></math>=<span>1D48A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6A;</mtext></math>=<span>1D48B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6B;</mtext></math>=<span>1D48C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6C;</mtext></math>=<span>1D48D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6D;</mtext></math>=<span>1D48E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6E;</mtext></math>=<span>1D48F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x6F;</mtext></math>=<span>1D490</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x70;</mtext></math>=<span>1D491</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x71;</mtext></math>=<span>1D492</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x72;</mtext></math>=<span>1D493</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x73;</mtext></math>=<span>1D494</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x74;</mtext></math>=<span>1D495</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x75;</mtext></math>=<span>1D496</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x76;</mtext></math>=<span>1D497</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x77;</mtext></math>=<span>1D498</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x78;</mtext></math>=<span>1D499</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x79;</mtext></math>=<span>1D49A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x7A;</mtext></math>=<span>1D49B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x391;</mtext></math>=<span>1D71C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x392;</mtext></math>=<span>1D71D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x393;</mtext></math>=<span>1D71E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x394;</mtext></math>=<span>1D71F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x395;</mtext></math>=<span>1D720</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x396;</mtext></math>=<span>1D721</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x397;</mtext></math>=<span>1D722</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x398;</mtext></math>=<span>1D723</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x399;</mtext></math>=<span>1D724</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39A;</mtext></math>=<span>1D725</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39B;</mtext></math>=<span>1D726</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39C;</mtext></math>=<span>1D727</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39D;</mtext></math>=<span>1D728</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39E;</mtext></math>=<span>1D729</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x39F;</mtext></math>=<span>1D72A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A0;</mtext></math>=<span>1D72B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A1;</mtext></math>=<span>1D72C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3F4;</mtext></math>=<span>1D72D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A3;</mtext></math>=<span>1D72E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A4;</mtext></math>=<span>1D72F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A5;</mtext></math>=<span>1D730</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A6;</mtext></math>=<span>1D731</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A7;</mtext></math>=<span>1D732</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A8;</mtext></math>=<span>1D733</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3A9;</mtext></math>=<span>1D734</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x2207;</mtext></math>=<span>1D735</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B1;</mtext></math>=<span>1D736</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B2;</mtext></math>=<span>1D737</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B3;</mtext></math>=<span>1D738</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B4;</mtext></math>=<span>1D739</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B5;</mtext></math>=<span>1D73A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B6;</mtext></math>=<span>1D73B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B7;</mtext></math>=<span>1D73C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B8;</mtext></math>=<span>1D73D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3B9;</mtext></math>=<span>1D73E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BA;</mtext></math>=<span>1D73F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BB;</mtext></math>=<span>1D740</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BC;</mtext></math>=<span>1D741</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BD;</mtext></math>=<span>1D742</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BE;</mtext></math>=<span>1D743</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3BF;</mtext></math>=<span>1D744</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C0;</mtext></math>=<span>1D745</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C1;</mtext></math>=<span>1D746</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C2;</mtext></math>=<span>1D747</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C3;</mtext></math>=<span>1D748</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C4;</mtext></math>=<span>1D749</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C5;</mtext></math>=<span>1D74A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C6;</mtext></math>=<span>1D74B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C7;</mtext></math>=<span>1D74C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C8;</mtext></math>=<span>1D74D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3C9;</mtext></math>=<span>1D74E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x2202;</mtext></math>=<span>1D74F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3F5;</mtext></math>=<span>1D750</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3D1;</mtext></math>=<span>1D751</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3F0;</mtext></math>=<span>1D752</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3D5;</mtext></math>=<span>1D753</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3F1;</mtext></math>=<span>1D754</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-italic">&#x3D6;</mtext></math>=<span>1D755</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-ref.html
new file mode 100644
index 0000000000..ac24ab5b00
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-ref.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D400;</mtext></math>=<span>1D400</span></span>
+ <span><math class="testfont"><mtext>&#x1D401;</mtext></math>=<span>1D401</span></span>
+ <span><math class="testfont"><mtext>&#x1D402;</mtext></math>=<span>1D402</span></span>
+ <span><math class="testfont"><mtext>&#x1D403;</mtext></math>=<span>1D403</span></span>
+ <span><math class="testfont"><mtext>&#x1D404;</mtext></math>=<span>1D404</span></span>
+ <span><math class="testfont"><mtext>&#x1D405;</mtext></math>=<span>1D405</span></span>
+ <span><math class="testfont"><mtext>&#x1D406;</mtext></math>=<span>1D406</span></span>
+ <span><math class="testfont"><mtext>&#x1D407;</mtext></math>=<span>1D407</span></span>
+ <span><math class="testfont"><mtext>&#x1D408;</mtext></math>=<span>1D408</span></span>
+ <span><math class="testfont"><mtext>&#x1D409;</mtext></math>=<span>1D409</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D40A;</mtext></math>=<span>1D40A</span></span>
+ <span><math class="testfont"><mtext>&#x1D40B;</mtext></math>=<span>1D40B</span></span>
+ <span><math class="testfont"><mtext>&#x1D40C;</mtext></math>=<span>1D40C</span></span>
+ <span><math class="testfont"><mtext>&#x1D40D;</mtext></math>=<span>1D40D</span></span>
+ <span><math class="testfont"><mtext>&#x1D40E;</mtext></math>=<span>1D40E</span></span>
+ <span><math class="testfont"><mtext>&#x1D40F;</mtext></math>=<span>1D40F</span></span>
+ <span><math class="testfont"><mtext>&#x1D410;</mtext></math>=<span>1D410</span></span>
+ <span><math class="testfont"><mtext>&#x1D411;</mtext></math>=<span>1D411</span></span>
+ <span><math class="testfont"><mtext>&#x1D412;</mtext></math>=<span>1D412</span></span>
+ <span><math class="testfont"><mtext>&#x1D413;</mtext></math>=<span>1D413</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D414;</mtext></math>=<span>1D414</span></span>
+ <span><math class="testfont"><mtext>&#x1D415;</mtext></math>=<span>1D415</span></span>
+ <span><math class="testfont"><mtext>&#x1D416;</mtext></math>=<span>1D416</span></span>
+ <span><math class="testfont"><mtext>&#x1D417;</mtext></math>=<span>1D417</span></span>
+ <span><math class="testfont"><mtext>&#x1D418;</mtext></math>=<span>1D418</span></span>
+ <span><math class="testfont"><mtext>&#x1D419;</mtext></math>=<span>1D419</span></span>
+ <span><math class="testfont"><mtext>&#x1D41A;</mtext></math>=<span>1D41A</span></span>
+ <span><math class="testfont"><mtext>&#x1D41B;</mtext></math>=<span>1D41B</span></span>
+ <span><math class="testfont"><mtext>&#x1D41C;</mtext></math>=<span>1D41C</span></span>
+ <span><math class="testfont"><mtext>&#x1D41D;</mtext></math>=<span>1D41D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D41E;</mtext></math>=<span>1D41E</span></span>
+ <span><math class="testfont"><mtext>&#x1D41F;</mtext></math>=<span>1D41F</span></span>
+ <span><math class="testfont"><mtext>&#x1D420;</mtext></math>=<span>1D420</span></span>
+ <span><math class="testfont"><mtext>&#x1D421;</mtext></math>=<span>1D421</span></span>
+ <span><math class="testfont"><mtext>&#x1D422;</mtext></math>=<span>1D422</span></span>
+ <span><math class="testfont"><mtext>&#x1D423;</mtext></math>=<span>1D423</span></span>
+ <span><math class="testfont"><mtext>&#x1D424;</mtext></math>=<span>1D424</span></span>
+ <span><math class="testfont"><mtext>&#x1D425;</mtext></math>=<span>1D425</span></span>
+ <span><math class="testfont"><mtext>&#x1D426;</mtext></math>=<span>1D426</span></span>
+ <span><math class="testfont"><mtext>&#x1D427;</mtext></math>=<span>1D427</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D428;</mtext></math>=<span>1D428</span></span>
+ <span><math class="testfont"><mtext>&#x1D429;</mtext></math>=<span>1D429</span></span>
+ <span><math class="testfont"><mtext>&#x1D42A;</mtext></math>=<span>1D42A</span></span>
+ <span><math class="testfont"><mtext>&#x1D42B;</mtext></math>=<span>1D42B</span></span>
+ <span><math class="testfont"><mtext>&#x1D42C;</mtext></math>=<span>1D42C</span></span>
+ <span><math class="testfont"><mtext>&#x1D42D;</mtext></math>=<span>1D42D</span></span>
+ <span><math class="testfont"><mtext>&#x1D42E;</mtext></math>=<span>1D42E</span></span>
+ <span><math class="testfont"><mtext>&#x1D42F;</mtext></math>=<span>1D42F</span></span>
+ <span><math class="testfont"><mtext>&#x1D430;</mtext></math>=<span>1D430</span></span>
+ <span><math class="testfont"><mtext>&#x1D431;</mtext></math>=<span>1D431</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D432;</mtext></math>=<span>1D432</span></span>
+ <span><math class="testfont"><mtext>&#x1D433;</mtext></math>=<span>1D433</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A8;</mtext></math>=<span>1D6A8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A9;</mtext></math>=<span>1D6A9</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AA;</mtext></math>=<span>1D6AA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AB;</mtext></math>=<span>1D6AB</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AC;</mtext></math>=<span>1D6AC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AD;</mtext></math>=<span>1D6AD</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AE;</mtext></math>=<span>1D6AE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6AF;</mtext></math>=<span>1D6AF</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6B0;</mtext></math>=<span>1D6B0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B1;</mtext></math>=<span>1D6B1</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B2;</mtext></math>=<span>1D6B2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B3;</mtext></math>=<span>1D6B3</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B4;</mtext></math>=<span>1D6B4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B5;</mtext></math>=<span>1D6B5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B6;</mtext></math>=<span>1D6B6</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B7;</mtext></math>=<span>1D6B7</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B8;</mtext></math>=<span>1D6B8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6B9;</mtext></math>=<span>1D6B9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6BA;</mtext></math>=<span>1D6BA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6BB;</mtext></math>=<span>1D6BB</span></span>
+ <span><math class="testfont"><mtext>&#x1D6BC;</mtext></math>=<span>1D6BC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6BD;</mtext></math>=<span>1D6BD</span></span>
+ <span><math class="testfont"><mtext>&#x1D6BE;</mtext></math>=<span>1D6BE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6BF;</mtext></math>=<span>1D6BF</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C0;</mtext></math>=<span>1D6C0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C1;</mtext></math>=<span>1D6C1</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C2;</mtext></math>=<span>1D6C2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C3;</mtext></math>=<span>1D6C3</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6C4;</mtext></math>=<span>1D6C4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C5;</mtext></math>=<span>1D6C5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C6;</mtext></math>=<span>1D6C6</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C7;</mtext></math>=<span>1D6C7</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C8;</mtext></math>=<span>1D6C8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6C9;</mtext></math>=<span>1D6C9</span></span>
+ <span><math class="testfont"><mtext>&#x1D6CA;</mtext></math>=<span>1D6CA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6CB;</mtext></math>=<span>1D6CB</span></span>
+ <span><math class="testfont"><mtext>&#x1D6CC;</mtext></math>=<span>1D6CC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6CD;</mtext></math>=<span>1D6CD</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6CE;</mtext></math>=<span>1D6CE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6CF;</mtext></math>=<span>1D6CF</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D0;</mtext></math>=<span>1D6D0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D1;</mtext></math>=<span>1D6D1</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D2;</mtext></math>=<span>1D6D2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D3;</mtext></math>=<span>1D6D3</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D4;</mtext></math>=<span>1D6D4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D5;</mtext></math>=<span>1D6D5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D6;</mtext></math>=<span>1D6D6</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D7;</mtext></math>=<span>1D6D7</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6D8;</mtext></math>=<span>1D6D8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6D9;</mtext></math>=<span>1D6D9</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DA;</mtext></math>=<span>1D6DA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DB;</mtext></math>=<span>1D6DB</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DC;</mtext></math>=<span>1D6DC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DD;</mtext></math>=<span>1D6DD</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DE;</mtext></math>=<span>1D6DE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6DF;</mtext></math>=<span>1D6DF</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E0;</mtext></math>=<span>1D6E0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E1;</mtext></math>=<span>1D6E1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7CA;</mtext></math>=<span>1D7CA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7CB;</mtext></math>=<span>1D7CB</span></span>
+ <span><math class="testfont"><mtext>&#x1D7CE;</mtext></math>=<span>1D7CE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7CF;</mtext></math>=<span>1D7CF</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D0;</mtext></math>=<span>1D7D0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D1;</mtext></math>=<span>1D7D1</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D2;</mtext></math>=<span>1D7D2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D3;</mtext></math>=<span>1D7D3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D4;</mtext></math>=<span>1D7D4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D5;</mtext></math>=<span>1D7D5</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7D6;</mtext></math>=<span>1D7D6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D7;</mtext></math>=<span>1D7D7</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif-ref.html
new file mode 100644
index 0000000000..78c0cc5ea6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif-ref.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-sans-serif (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D5D4;</mtext></math>=<span>1D5D4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D5;</mtext></math>=<span>1D5D5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D6;</mtext></math>=<span>1D5D6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D7;</mtext></math>=<span>1D5D7</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D8;</mtext></math>=<span>1D5D8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D9;</mtext></math>=<span>1D5D9</span></span>
+ <span><math class="testfont"><mtext>&#x1D5DA;</mtext></math>=<span>1D5DA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5DB;</mtext></math>=<span>1D5DB</span></span>
+ <span><math class="testfont"><mtext>&#x1D5DC;</mtext></math>=<span>1D5DC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5DD;</mtext></math>=<span>1D5DD</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5DE;</mtext></math>=<span>1D5DE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5DF;</mtext></math>=<span>1D5DF</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E0;</mtext></math>=<span>1D5E0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E1;</mtext></math>=<span>1D5E1</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E2;</mtext></math>=<span>1D5E2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E3;</mtext></math>=<span>1D5E3</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E4;</mtext></math>=<span>1D5E4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E5;</mtext></math>=<span>1D5E5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E6;</mtext></math>=<span>1D5E6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E7;</mtext></math>=<span>1D5E7</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5E8;</mtext></math>=<span>1D5E8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5E9;</mtext></math>=<span>1D5E9</span></span>
+ <span><math class="testfont"><mtext>&#x1D5EA;</mtext></math>=<span>1D5EA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5EB;</mtext></math>=<span>1D5EB</span></span>
+ <span><math class="testfont"><mtext>&#x1D5EC;</mtext></math>=<span>1D5EC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5ED;</mtext></math>=<span>1D5ED</span></span>
+ <span><math class="testfont"><mtext>&#x1D5EE;</mtext></math>=<span>1D5EE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5EF;</mtext></math>=<span>1D5EF</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F0;</mtext></math>=<span>1D5F0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F1;</mtext></math>=<span>1D5F1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5F2;</mtext></math>=<span>1D5F2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F3;</mtext></math>=<span>1D5F3</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F4;</mtext></math>=<span>1D5F4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F5;</mtext></math>=<span>1D5F5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F6;</mtext></math>=<span>1D5F6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F7;</mtext></math>=<span>1D5F7</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F8;</mtext></math>=<span>1D5F8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5F9;</mtext></math>=<span>1D5F9</span></span>
+ <span><math class="testfont"><mtext>&#x1D5FA;</mtext></math>=<span>1D5FA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5FB;</mtext></math>=<span>1D5FB</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5FC;</mtext></math>=<span>1D5FC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5FD;</mtext></math>=<span>1D5FD</span></span>
+ <span><math class="testfont"><mtext>&#x1D5FE;</mtext></math>=<span>1D5FE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5FF;</mtext></math>=<span>1D5FF</span></span>
+ <span><math class="testfont"><mtext>&#x1D600;</mtext></math>=<span>1D600</span></span>
+ <span><math class="testfont"><mtext>&#x1D601;</mtext></math>=<span>1D601</span></span>
+ <span><math class="testfont"><mtext>&#x1D602;</mtext></math>=<span>1D602</span></span>
+ <span><math class="testfont"><mtext>&#x1D603;</mtext></math>=<span>1D603</span></span>
+ <span><math class="testfont"><mtext>&#x1D604;</mtext></math>=<span>1D604</span></span>
+ <span><math class="testfont"><mtext>&#x1D605;</mtext></math>=<span>1D605</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D606;</mtext></math>=<span>1D606</span></span>
+ <span><math class="testfont"><mtext>&#x1D607;</mtext></math>=<span>1D607</span></span>
+ <span><math class="testfont"><mtext>&#x1D756;</mtext></math>=<span>1D756</span></span>
+ <span><math class="testfont"><mtext>&#x1D757;</mtext></math>=<span>1D757</span></span>
+ <span><math class="testfont"><mtext>&#x1D758;</mtext></math>=<span>1D758</span></span>
+ <span><math class="testfont"><mtext>&#x1D759;</mtext></math>=<span>1D759</span></span>
+ <span><math class="testfont"><mtext>&#x1D75A;</mtext></math>=<span>1D75A</span></span>
+ <span><math class="testfont"><mtext>&#x1D75B;</mtext></math>=<span>1D75B</span></span>
+ <span><math class="testfont"><mtext>&#x1D75C;</mtext></math>=<span>1D75C</span></span>
+ <span><math class="testfont"><mtext>&#x1D75D;</mtext></math>=<span>1D75D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D75E;</mtext></math>=<span>1D75E</span></span>
+ <span><math class="testfont"><mtext>&#x1D75F;</mtext></math>=<span>1D75F</span></span>
+ <span><math class="testfont"><mtext>&#x1D760;</mtext></math>=<span>1D760</span></span>
+ <span><math class="testfont"><mtext>&#x1D761;</mtext></math>=<span>1D761</span></span>
+ <span><math class="testfont"><mtext>&#x1D762;</mtext></math>=<span>1D762</span></span>
+ <span><math class="testfont"><mtext>&#x1D763;</mtext></math>=<span>1D763</span></span>
+ <span><math class="testfont"><mtext>&#x1D764;</mtext></math>=<span>1D764</span></span>
+ <span><math class="testfont"><mtext>&#x1D765;</mtext></math>=<span>1D765</span></span>
+ <span><math class="testfont"><mtext>&#x1D766;</mtext></math>=<span>1D766</span></span>
+ <span><math class="testfont"><mtext>&#x1D767;</mtext></math>=<span>1D767</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D768;</mtext></math>=<span>1D768</span></span>
+ <span><math class="testfont"><mtext>&#x1D769;</mtext></math>=<span>1D769</span></span>
+ <span><math class="testfont"><mtext>&#x1D76A;</mtext></math>=<span>1D76A</span></span>
+ <span><math class="testfont"><mtext>&#x1D76B;</mtext></math>=<span>1D76B</span></span>
+ <span><math class="testfont"><mtext>&#x1D76C;</mtext></math>=<span>1D76C</span></span>
+ <span><math class="testfont"><mtext>&#x1D76D;</mtext></math>=<span>1D76D</span></span>
+ <span><math class="testfont"><mtext>&#x1D76E;</mtext></math>=<span>1D76E</span></span>
+ <span><math class="testfont"><mtext>&#x1D76F;</mtext></math>=<span>1D76F</span></span>
+ <span><math class="testfont"><mtext>&#x1D770;</mtext></math>=<span>1D770</span></span>
+ <span><math class="testfont"><mtext>&#x1D771;</mtext></math>=<span>1D771</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D772;</mtext></math>=<span>1D772</span></span>
+ <span><math class="testfont"><mtext>&#x1D773;</mtext></math>=<span>1D773</span></span>
+ <span><math class="testfont"><mtext>&#x1D774;</mtext></math>=<span>1D774</span></span>
+ <span><math class="testfont"><mtext>&#x1D775;</mtext></math>=<span>1D775</span></span>
+ <span><math class="testfont"><mtext>&#x1D776;</mtext></math>=<span>1D776</span></span>
+ <span><math class="testfont"><mtext>&#x1D777;</mtext></math>=<span>1D777</span></span>
+ <span><math class="testfont"><mtext>&#x1D778;</mtext></math>=<span>1D778</span></span>
+ <span><math class="testfont"><mtext>&#x1D779;</mtext></math>=<span>1D779</span></span>
+ <span><math class="testfont"><mtext>&#x1D77A;</mtext></math>=<span>1D77A</span></span>
+ <span><math class="testfont"><mtext>&#x1D77B;</mtext></math>=<span>1D77B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D77C;</mtext></math>=<span>1D77C</span></span>
+ <span><math class="testfont"><mtext>&#x1D77D;</mtext></math>=<span>1D77D</span></span>
+ <span><math class="testfont"><mtext>&#x1D77E;</mtext></math>=<span>1D77E</span></span>
+ <span><math class="testfont"><mtext>&#x1D77F;</mtext></math>=<span>1D77F</span></span>
+ <span><math class="testfont"><mtext>&#x1D780;</mtext></math>=<span>1D780</span></span>
+ <span><math class="testfont"><mtext>&#x1D781;</mtext></math>=<span>1D781</span></span>
+ <span><math class="testfont"><mtext>&#x1D782;</mtext></math>=<span>1D782</span></span>
+ <span><math class="testfont"><mtext>&#x1D783;</mtext></math>=<span>1D783</span></span>
+ <span><math class="testfont"><mtext>&#x1D784;</mtext></math>=<span>1D784</span></span>
+ <span><math class="testfont"><mtext>&#x1D785;</mtext></math>=<span>1D785</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D786;</mtext></math>=<span>1D786</span></span>
+ <span><math class="testfont"><mtext>&#x1D787;</mtext></math>=<span>1D787</span></span>
+ <span><math class="testfont"><mtext>&#x1D788;</mtext></math>=<span>1D788</span></span>
+ <span><math class="testfont"><mtext>&#x1D789;</mtext></math>=<span>1D789</span></span>
+ <span><math class="testfont"><mtext>&#x1D78A;</mtext></math>=<span>1D78A</span></span>
+ <span><math class="testfont"><mtext>&#x1D78B;</mtext></math>=<span>1D78B</span></span>
+ <span><math class="testfont"><mtext>&#x1D78C;</mtext></math>=<span>1D78C</span></span>
+ <span><math class="testfont"><mtext>&#x1D78D;</mtext></math>=<span>1D78D</span></span>
+ <span><math class="testfont"><mtext>&#x1D78E;</mtext></math>=<span>1D78E</span></span>
+ <span><math class="testfont"><mtext>&#x1D78F;</mtext></math>=<span>1D78F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7EC;</mtext></math>=<span>1D7EC</span></span>
+ <span><math class="testfont"><mtext>&#x1D7ED;</mtext></math>=<span>1D7ED</span></span>
+ <span><math class="testfont"><mtext>&#x1D7EE;</mtext></math>=<span>1D7EE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7EF;</mtext></math>=<span>1D7EF</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F0;</mtext></math>=<span>1D7F0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F1;</mtext></math>=<span>1D7F1</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F2;</mtext></math>=<span>1D7F2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F3;</mtext></math>=<span>1D7F3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F4;</mtext></math>=<span>1D7F4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F5;</mtext></math>=<span>1D7F5</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif.html
new file mode 100644
index 0000000000..0e0662dff6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-sans-serif.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-sans-serif</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#bold-sans-serif-mappings">
+<link rel="match" href="mathvariant-bold-sans-serif-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-sans-serif mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x41;</mtext></math>=<span>1D5D4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x42;</mtext></math>=<span>1D5D5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x43;</mtext></math>=<span>1D5D6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x44;</mtext></math>=<span>1D5D7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x45;</mtext></math>=<span>1D5D8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x46;</mtext></math>=<span>1D5D9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x47;</mtext></math>=<span>1D5DA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x48;</mtext></math>=<span>1D5DB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x49;</mtext></math>=<span>1D5DC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4A;</mtext></math>=<span>1D5DD</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4B;</mtext></math>=<span>1D5DE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4C;</mtext></math>=<span>1D5DF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4D;</mtext></math>=<span>1D5E0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4E;</mtext></math>=<span>1D5E1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x4F;</mtext></math>=<span>1D5E2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x50;</mtext></math>=<span>1D5E3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x51;</mtext></math>=<span>1D5E4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x52;</mtext></math>=<span>1D5E5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x53;</mtext></math>=<span>1D5E6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x54;</mtext></math>=<span>1D5E7</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x55;</mtext></math>=<span>1D5E8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x56;</mtext></math>=<span>1D5E9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x57;</mtext></math>=<span>1D5EA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x58;</mtext></math>=<span>1D5EB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x59;</mtext></math>=<span>1D5EC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x5A;</mtext></math>=<span>1D5ED</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x61;</mtext></math>=<span>1D5EE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x62;</mtext></math>=<span>1D5EF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x63;</mtext></math>=<span>1D5F0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x64;</mtext></math>=<span>1D5F1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x65;</mtext></math>=<span>1D5F2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x66;</mtext></math>=<span>1D5F3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x67;</mtext></math>=<span>1D5F4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x68;</mtext></math>=<span>1D5F5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x69;</mtext></math>=<span>1D5F6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6A;</mtext></math>=<span>1D5F7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6B;</mtext></math>=<span>1D5F8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6C;</mtext></math>=<span>1D5F9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6D;</mtext></math>=<span>1D5FA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6E;</mtext></math>=<span>1D5FB</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x6F;</mtext></math>=<span>1D5FC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x70;</mtext></math>=<span>1D5FD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x71;</mtext></math>=<span>1D5FE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x72;</mtext></math>=<span>1D5FF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x73;</mtext></math>=<span>1D600</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x74;</mtext></math>=<span>1D601</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x75;</mtext></math>=<span>1D602</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x76;</mtext></math>=<span>1D603</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x77;</mtext></math>=<span>1D604</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x78;</mtext></math>=<span>1D605</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x79;</mtext></math>=<span>1D606</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x7A;</mtext></math>=<span>1D607</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x391;</mtext></math>=<span>1D756</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x392;</mtext></math>=<span>1D757</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x393;</mtext></math>=<span>1D758</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x394;</mtext></math>=<span>1D759</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x395;</mtext></math>=<span>1D75A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x396;</mtext></math>=<span>1D75B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x397;</mtext></math>=<span>1D75C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x398;</mtext></math>=<span>1D75D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x399;</mtext></math>=<span>1D75E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39A;</mtext></math>=<span>1D75F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39B;</mtext></math>=<span>1D760</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39C;</mtext></math>=<span>1D761</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39D;</mtext></math>=<span>1D762</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39E;</mtext></math>=<span>1D763</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39F;</mtext></math>=<span>1D764</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A0;</mtext></math>=<span>1D765</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A1;</mtext></math>=<span>1D766</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3F4;</mtext></math>=<span>1D767</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A3;</mtext></math>=<span>1D768</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A4;</mtext></math>=<span>1D769</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A5;</mtext></math>=<span>1D76A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A6;</mtext></math>=<span>1D76B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A7;</mtext></math>=<span>1D76C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A8;</mtext></math>=<span>1D76D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3A9;</mtext></math>=<span>1D76E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x2207;</mtext></math>=<span>1D76F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B1;</mtext></math>=<span>1D770</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B2;</mtext></math>=<span>1D771</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B3;</mtext></math>=<span>1D772</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B4;</mtext></math>=<span>1D773</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B5;</mtext></math>=<span>1D774</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B6;</mtext></math>=<span>1D775</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B7;</mtext></math>=<span>1D776</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B8;</mtext></math>=<span>1D777</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3B9;</mtext></math>=<span>1D778</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BA;</mtext></math>=<span>1D779</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BB;</mtext></math>=<span>1D77A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BC;</mtext></math>=<span>1D77B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BD;</mtext></math>=<span>1D77C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BE;</mtext></math>=<span>1D77D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3BF;</mtext></math>=<span>1D77E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C0;</mtext></math>=<span>1D77F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C1;</mtext></math>=<span>1D780</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C2;</mtext></math>=<span>1D781</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C3;</mtext></math>=<span>1D782</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C4;</mtext></math>=<span>1D783</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C5;</mtext></math>=<span>1D784</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C6;</mtext></math>=<span>1D785</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C7;</mtext></math>=<span>1D786</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C8;</mtext></math>=<span>1D787</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3C9;</mtext></math>=<span>1D788</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x2202;</mtext></math>=<span>1D789</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3F5;</mtext></math>=<span>1D78A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3D1;</mtext></math>=<span>1D78B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3F0;</mtext></math>=<span>1D78C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3D5;</mtext></math>=<span>1D78D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3F1;</mtext></math>=<span>1D78E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x3D6;</mtext></math>=<span>1D78F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x30;</mtext></math>=<span>1D7EC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x31;</mtext></math>=<span>1D7ED</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x32;</mtext></math>=<span>1D7EE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x33;</mtext></math>=<span>1D7EF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x34;</mtext></math>=<span>1D7F0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x35;</mtext></math>=<span>1D7F1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x36;</mtext></math>=<span>1D7F2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x37;</mtext></math>=<span>1D7F3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x38;</mtext></math>=<span>1D7F4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-sans-serif">&#x39;</mtext></math>=<span>1D7F5</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script-ref.html
new file mode 100644
index 0000000000..ef11f7fb8f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-script (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D4D0;</mtext></math>=<span>1D4D0</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D1;</mtext></math>=<span>1D4D1</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D2;</mtext></math>=<span>1D4D2</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D3;</mtext></math>=<span>1D4D3</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D4;</mtext></math>=<span>1D4D4</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D5;</mtext></math>=<span>1D4D5</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D6;</mtext></math>=<span>1D4D6</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D7;</mtext></math>=<span>1D4D7</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D8;</mtext></math>=<span>1D4D8</span></span>
+ <span><math class="testfont"><mtext>&#x1D4D9;</mtext></math>=<span>1D4D9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4DA;</mtext></math>=<span>1D4DA</span></span>
+ <span><math class="testfont"><mtext>&#x1D4DB;</mtext></math>=<span>1D4DB</span></span>
+ <span><math class="testfont"><mtext>&#x1D4DC;</mtext></math>=<span>1D4DC</span></span>
+ <span><math class="testfont"><mtext>&#x1D4DD;</mtext></math>=<span>1D4DD</span></span>
+ <span><math class="testfont"><mtext>&#x1D4DE;</mtext></math>=<span>1D4DE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4DF;</mtext></math>=<span>1D4DF</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E0;</mtext></math>=<span>1D4E0</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E1;</mtext></math>=<span>1D4E1</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E2;</mtext></math>=<span>1D4E2</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E3;</mtext></math>=<span>1D4E3</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4E4;</mtext></math>=<span>1D4E4</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E5;</mtext></math>=<span>1D4E5</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E6;</mtext></math>=<span>1D4E6</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E7;</mtext></math>=<span>1D4E7</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E8;</mtext></math>=<span>1D4E8</span></span>
+ <span><math class="testfont"><mtext>&#x1D4E9;</mtext></math>=<span>1D4E9</span></span>
+ <span><math class="testfont"><mtext>&#x1D4EA;</mtext></math>=<span>1D4EA</span></span>
+ <span><math class="testfont"><mtext>&#x1D4EB;</mtext></math>=<span>1D4EB</span></span>
+ <span><math class="testfont"><mtext>&#x1D4EC;</mtext></math>=<span>1D4EC</span></span>
+ <span><math class="testfont"><mtext>&#x1D4ED;</mtext></math>=<span>1D4ED</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4EE;</mtext></math>=<span>1D4EE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4EF;</mtext></math>=<span>1D4EF</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F0;</mtext></math>=<span>1D4F0</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F1;</mtext></math>=<span>1D4F1</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F2;</mtext></math>=<span>1D4F2</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F3;</mtext></math>=<span>1D4F3</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F4;</mtext></math>=<span>1D4F4</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F5;</mtext></math>=<span>1D4F5</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F6;</mtext></math>=<span>1D4F6</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F7;</mtext></math>=<span>1D4F7</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4F8;</mtext></math>=<span>1D4F8</span></span>
+ <span><math class="testfont"><mtext>&#x1D4F9;</mtext></math>=<span>1D4F9</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FA;</mtext></math>=<span>1D4FA</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FB;</mtext></math>=<span>1D4FB</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FC;</mtext></math>=<span>1D4FC</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FD;</mtext></math>=<span>1D4FD</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FE;</mtext></math>=<span>1D4FE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4FF;</mtext></math>=<span>1D4FF</span></span>
+ <span><math class="testfont"><mtext>&#x1D500;</mtext></math>=<span>1D500</span></span>
+ <span><math class="testfont"><mtext>&#x1D501;</mtext></math>=<span>1D501</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D502;</mtext></math>=<span>1D502</span></span>
+ <span><math class="testfont"><mtext>&#x1D503;</mtext></math>=<span>1D503</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script.html
new file mode 100644
index 0000000000..0e775949f9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold-script.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold-script</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#bold-script-mappings">
+<link rel="match" href="mathvariant-bold-script-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-script mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x41;</mtext></math>=<span>1D4D0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x42;</mtext></math>=<span>1D4D1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x43;</mtext></math>=<span>1D4D2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x44;</mtext></math>=<span>1D4D3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x45;</mtext></math>=<span>1D4D4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x46;</mtext></math>=<span>1D4D5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x47;</mtext></math>=<span>1D4D6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x48;</mtext></math>=<span>1D4D7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x49;</mtext></math>=<span>1D4D8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4A;</mtext></math>=<span>1D4D9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4B;</mtext></math>=<span>1D4DA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4C;</mtext></math>=<span>1D4DB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4D;</mtext></math>=<span>1D4DC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4E;</mtext></math>=<span>1D4DD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x4F;</mtext></math>=<span>1D4DE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x50;</mtext></math>=<span>1D4DF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x51;</mtext></math>=<span>1D4E0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x52;</mtext></math>=<span>1D4E1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x53;</mtext></math>=<span>1D4E2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x54;</mtext></math>=<span>1D4E3</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x55;</mtext></math>=<span>1D4E4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x56;</mtext></math>=<span>1D4E5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x57;</mtext></math>=<span>1D4E6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x58;</mtext></math>=<span>1D4E7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x59;</mtext></math>=<span>1D4E8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x5A;</mtext></math>=<span>1D4E9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x61;</mtext></math>=<span>1D4EA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x62;</mtext></math>=<span>1D4EB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x63;</mtext></math>=<span>1D4EC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x64;</mtext></math>=<span>1D4ED</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x65;</mtext></math>=<span>1D4EE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x66;</mtext></math>=<span>1D4EF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x67;</mtext></math>=<span>1D4F0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x68;</mtext></math>=<span>1D4F1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x69;</mtext></math>=<span>1D4F2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6A;</mtext></math>=<span>1D4F3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6B;</mtext></math>=<span>1D4F4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6C;</mtext></math>=<span>1D4F5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6D;</mtext></math>=<span>1D4F6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6E;</mtext></math>=<span>1D4F7</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x6F;</mtext></math>=<span>1D4F8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x70;</mtext></math>=<span>1D4F9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x71;</mtext></math>=<span>1D4FA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x72;</mtext></math>=<span>1D4FB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x73;</mtext></math>=<span>1D4FC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x74;</mtext></math>=<span>1D4FD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x75;</mtext></math>=<span>1D4FE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x76;</mtext></math>=<span>1D4FF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x77;</mtext></math>=<span>1D500</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x78;</mtext></math>=<span>1D501</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x79;</mtext></math>=<span>1D502</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold-script">&#x7A;</mtext></math>=<span>1D503</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold.html
new file mode 100644
index 0000000000..db5f4755be
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-bold.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant bold</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#bold-mappings">
+<link rel="match" href="mathvariant-bold-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a bold mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x41;</mtext></math>=<span>1D400</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x42;</mtext></math>=<span>1D401</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x43;</mtext></math>=<span>1D402</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x44;</mtext></math>=<span>1D403</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x45;</mtext></math>=<span>1D404</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x46;</mtext></math>=<span>1D405</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x47;</mtext></math>=<span>1D406</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x48;</mtext></math>=<span>1D407</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x49;</mtext></math>=<span>1D408</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4A;</mtext></math>=<span>1D409</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4B;</mtext></math>=<span>1D40A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4C;</mtext></math>=<span>1D40B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4D;</mtext></math>=<span>1D40C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4E;</mtext></math>=<span>1D40D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x4F;</mtext></math>=<span>1D40E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x50;</mtext></math>=<span>1D40F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x51;</mtext></math>=<span>1D410</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x52;</mtext></math>=<span>1D411</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x53;</mtext></math>=<span>1D412</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x54;</mtext></math>=<span>1D413</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x55;</mtext></math>=<span>1D414</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x56;</mtext></math>=<span>1D415</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x57;</mtext></math>=<span>1D416</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x58;</mtext></math>=<span>1D417</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x59;</mtext></math>=<span>1D418</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x5A;</mtext></math>=<span>1D419</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x61;</mtext></math>=<span>1D41A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x62;</mtext></math>=<span>1D41B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x63;</mtext></math>=<span>1D41C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x64;</mtext></math>=<span>1D41D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x65;</mtext></math>=<span>1D41E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x66;</mtext></math>=<span>1D41F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x67;</mtext></math>=<span>1D420</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x68;</mtext></math>=<span>1D421</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x69;</mtext></math>=<span>1D422</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6A;</mtext></math>=<span>1D423</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6B;</mtext></math>=<span>1D424</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6C;</mtext></math>=<span>1D425</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6D;</mtext></math>=<span>1D426</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6E;</mtext></math>=<span>1D427</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x6F;</mtext></math>=<span>1D428</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x70;</mtext></math>=<span>1D429</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x71;</mtext></math>=<span>1D42A</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x72;</mtext></math>=<span>1D42B</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x73;</mtext></math>=<span>1D42C</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x74;</mtext></math>=<span>1D42D</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x75;</mtext></math>=<span>1D42E</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x76;</mtext></math>=<span>1D42F</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x77;</mtext></math>=<span>1D430</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x78;</mtext></math>=<span>1D431</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x79;</mtext></math>=<span>1D432</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x7A;</mtext></math>=<span>1D433</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x391;</mtext></math>=<span>1D6A8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x392;</mtext></math>=<span>1D6A9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x393;</mtext></math>=<span>1D6AA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x394;</mtext></math>=<span>1D6AB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x395;</mtext></math>=<span>1D6AC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x396;</mtext></math>=<span>1D6AD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x397;</mtext></math>=<span>1D6AE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x398;</mtext></math>=<span>1D6AF</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x399;</mtext></math>=<span>1D6B0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39A;</mtext></math>=<span>1D6B1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39B;</mtext></math>=<span>1D6B2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39C;</mtext></math>=<span>1D6B3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39D;</mtext></math>=<span>1D6B4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39E;</mtext></math>=<span>1D6B5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39F;</mtext></math>=<span>1D6B6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A0;</mtext></math>=<span>1D6B7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A1;</mtext></math>=<span>1D6B8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3F4;</mtext></math>=<span>1D6B9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A3;</mtext></math>=<span>1D6BA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A4;</mtext></math>=<span>1D6BB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A5;</mtext></math>=<span>1D6BC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A6;</mtext></math>=<span>1D6BD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A7;</mtext></math>=<span>1D6BE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A8;</mtext></math>=<span>1D6BF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3A9;</mtext></math>=<span>1D6C0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x2207;</mtext></math>=<span>1D6C1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B1;</mtext></math>=<span>1D6C2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B2;</mtext></math>=<span>1D6C3</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B3;</mtext></math>=<span>1D6C4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B4;</mtext></math>=<span>1D6C5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B5;</mtext></math>=<span>1D6C6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B6;</mtext></math>=<span>1D6C7</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B7;</mtext></math>=<span>1D6C8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B8;</mtext></math>=<span>1D6C9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3B9;</mtext></math>=<span>1D6CA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BA;</mtext></math>=<span>1D6CB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BB;</mtext></math>=<span>1D6CC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BC;</mtext></math>=<span>1D6CD</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BD;</mtext></math>=<span>1D6CE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BE;</mtext></math>=<span>1D6CF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3BF;</mtext></math>=<span>1D6D0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C0;</mtext></math>=<span>1D6D1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C1;</mtext></math>=<span>1D6D2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C2;</mtext></math>=<span>1D6D3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C3;</mtext></math>=<span>1D6D4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C4;</mtext></math>=<span>1D6D5</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C5;</mtext></math>=<span>1D6D6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C6;</mtext></math>=<span>1D6D7</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C7;</mtext></math>=<span>1D6D8</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C8;</mtext></math>=<span>1D6D9</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3C9;</mtext></math>=<span>1D6DA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x2202;</mtext></math>=<span>1D6DB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3F5;</mtext></math>=<span>1D6DC</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3D1;</mtext></math>=<span>1D6DD</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3F0;</mtext></math>=<span>1D6DE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3D5;</mtext></math>=<span>1D6DF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3F1;</mtext></math>=<span>1D6E0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3D6;</mtext></math>=<span>1D6E1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3DC;</mtext></math>=<span>1D7CA</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x3DD;</mtext></math>=<span>1D7CB</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x30;</mtext></math>=<span>1D7CE</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x31;</mtext></math>=<span>1D7CF</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x32;</mtext></math>=<span>1D7D0</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x33;</mtext></math>=<span>1D7D1</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x34;</mtext></math>=<span>1D7D2</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x35;</mtext></math>=<span>1D7D3</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x36;</mtext></math>=<span>1D7D4</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x37;</mtext></math>=<span>1D7D5</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x38;</mtext></math>=<span>1D7D6</span></span>
+ <span><math class="testfont"><mtext mathvariant="bold">&#x39;</mtext></math>=<span>1D7D7</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity-ref.html
new file mode 100644
index 0000000000..28d9acc1f4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity-ref.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant case sensitivity</title>
+<style>
+ @font-face {
+ font-family: mathvariant-bold-fraktur;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-italic;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-sans-serif;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-script;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-double-struck;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ @font-face {
+ font-family: mathvariant-fraktur;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-initial;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ @font-face {
+ font-family: mathvariant-italic;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-looped;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ @font-face {
+ font-family: mathvariant-monospace;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-bold-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-script;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-stretched;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ @font-face {
+ font-family: mathvariant-tailed;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+</style>
+<body>
+ <p>
+ <math style="font-family: mathvariant-bold-fraktur">
+ <mtext>&#x1D56C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold">
+ <mtext>&#x1D400;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-italic">
+ <mtext>&#x1D468;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-sans-serif">
+ <mtext>&#x1D5D4;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-script">
+ <mtext>&#x1D4D0;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-double-struck">
+ <mtext>&#x1D538;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-fraktur">
+ <mtext>&#x1D504;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-initial">
+ <mtext>&#x1EE30;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-italic">
+ <mtext>&#x1D434;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-looped">
+ <mtext>&#x1EE90;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-monospace">
+ <mtext>&#x1D670;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-bold-italic">
+ <mtext>&#x1D63C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif">
+ <mtext>&#x1D5A0;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-italic">
+ <mtext>&#x1D608;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-script">
+ <mtext>&#x1D49C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-stretched">
+ <mtext>&#x1EE70;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-tailed">
+ <mtext>&#x1EE52;</mtext>
+ </math>
+ </p>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity.html
new file mode 100644
index 0000000000..21c8300a7a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-case-sensitivity.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant case sensitivity</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="match" href="mathvariant-case-sensitivity-ref.html"/>
+<meta name="assert" content="Verify that mathvariant value is case insensitive">
+<style>
+ @font-face {
+ font-family: mathvariant-bold-fraktur;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-italic;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-sans-serif;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-script;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-double-struck;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ @font-face {
+ font-family: mathvariant-fraktur;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-initial;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ @font-face {
+ font-family: mathvariant-italic;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-looped;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ @font-face {
+ font-family: mathvariant-monospace;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-bold-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-script;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-stretched;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ @font-face {
+ font-family: mathvariant-tailed;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+</style>
+<body>
+ <p>
+ <math style="font-family: mathvariant-bold-fraktur">
+ <mtext mathvariant="BoLd-fRaKtUr">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold">
+ <mtext mathvariant="BoLd">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-italic">
+ <mtext mathvariant="BoLd-iTaLiC">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-sans-serif">
+ <mtext mathvariant="BoLd-sAnS-SeRiF">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-script">
+ <mtext mathvariant="BoLd-sCrIpT">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-double-struck">
+ <mtext mathvariant="DoUbLe-sTrUcK">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-fraktur">
+ <mtext mathvariant="FrAkTuR">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-initial">
+ <mtext mathvariant="InItIaL">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-italic">
+ <mtext mathvariant="ItAlIc">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-looped">
+ <mtext mathvariant="LoOpEd">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-monospace">
+ <mtext mathvariant="MoNoSpAcE">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-bold-italic">
+ <mtext mathvariant="SaNs-sErIf-bOlD-ItAlIc">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif">
+ <mtext mathvariant="SaNs-sErIf">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-italic">
+ <mtext mathvariant="SaNs-sErIf-iTaLiC">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-script">
+ <mtext mathvariant="ScRiPt">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-stretched">
+ <mtext mathvariant="StReTcHeD">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-tailed">
+ <mtext mathvariant="TaIlEd">&#x642;</mtext>
+ </math>
+ </p>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight-ref.html
new file mode 100644
index 0000000000..817723a62d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>mathvariant="double-struck" and font-style/font-weight (reference)</title>
+ <style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 32px;
+ }
+ .italic { font-style: italic; }
+ .bold { font-weight: bold; }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if you see three lines with text <span class="testfont">&#x1EEA1;</span> respectively rendered with italic, bold and bold-italic style:</p>
+ <p><math class="testfont"><mtext class="italic">&#x1EEA1;</mtext></math></p>
+ <p><math class="testfont"><mtext class="bold">&#x1EEA1;</mtext></math></p>
+ <p><math class="testfont"><mtext class="bold italic">&#x1EEA1;</mtext></math></p>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight.html
new file mode 100644
index 0000000000..2e283e1d70
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-font-style-font-weight.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>mathvariant="double-struck" and font-style/font-weight</title>
+ <link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1789081">
+ <link rel="match" href="mathvariant-double-struck-font-style-font-weight-ref.html"/>
+ <meta name="assert" content="Verify that mathvariant='double-struck' don't reset the font-style/font-weight properties.">
+ <style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 32px;
+ }
+ .italic { font-style: italic; }
+ .bold { font-weight: bold; }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if you see three lines with text <span class="testfont">&#x1EEA1;</span> respectively rendered with italic, bold and bold-italic style:</p>
+ <p><math class="testfont"><mtext mathvariant="double-struck" class="italic">&#x628;</mtext></math></p>
+ <p><math class="testfont"><mtext mathvariant="double-struck" class="bold">&#x628;</mtext></math></p>
+ <p><math class="testfont"><mtext mathvariant="double-struck" class="bold italic">&#x628;</mtext></math></p>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-ref.html
new file mode 100644
index 0000000000..ebdb7a15b0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck-ref.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant double-struck (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D538;</mtext></math>=<span>1D538</span></span>
+ <span><math class="testfont"><mtext>&#x1D539;</mtext></math>=<span>1D539</span></span>
+ <span><math class="testfont"><mtext>&#x2102;</mtext></math>=<span>02102</span></span>
+ <span><math class="testfont"><mtext>&#x1D53B;</mtext></math>=<span>1D53B</span></span>
+ <span><math class="testfont"><mtext>&#x1D53C;</mtext></math>=<span>1D53C</span></span>
+ <span><math class="testfont"><mtext>&#x1D53D;</mtext></math>=<span>1D53D</span></span>
+ <span><math class="testfont"><mtext>&#x1D53E;</mtext></math>=<span>1D53E</span></span>
+ <span><math class="testfont"><mtext>&#x210D;</mtext></math>=<span>0210D</span></span>
+ <span><math class="testfont"><mtext>&#x1D540;</mtext></math>=<span>1D540</span></span>
+ <span><math class="testfont"><mtext>&#x1D541;</mtext></math>=<span>1D541</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D542;</mtext></math>=<span>1D542</span></span>
+ <span><math class="testfont"><mtext>&#x1D543;</mtext></math>=<span>1D543</span></span>
+ <span><math class="testfont"><mtext>&#x1D544;</mtext></math>=<span>1D544</span></span>
+ <span><math class="testfont"><mtext>&#x2115;</mtext></math>=<span>02115</span></span>
+ <span><math class="testfont"><mtext>&#x1D546;</mtext></math>=<span>1D546</span></span>
+ <span><math class="testfont"><mtext>&#x2119;</mtext></math>=<span>02119</span></span>
+ <span><math class="testfont"><mtext>&#x211A;</mtext></math>=<span>0211A</span></span>
+ <span><math class="testfont"><mtext>&#x211D;</mtext></math>=<span>0211D</span></span>
+ <span><math class="testfont"><mtext>&#x1D54A;</mtext></math>=<span>1D54A</span></span>
+ <span><math class="testfont"><mtext>&#x1D54B;</mtext></math>=<span>1D54B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D54C;</mtext></math>=<span>1D54C</span></span>
+ <span><math class="testfont"><mtext>&#x1D54D;</mtext></math>=<span>1D54D</span></span>
+ <span><math class="testfont"><mtext>&#x1D54E;</mtext></math>=<span>1D54E</span></span>
+ <span><math class="testfont"><mtext>&#x1D54F;</mtext></math>=<span>1D54F</span></span>
+ <span><math class="testfont"><mtext>&#x1D550;</mtext></math>=<span>1D550</span></span>
+ <span><math class="testfont"><mtext>&#x2124;</mtext></math>=<span>02124</span></span>
+ <span><math class="testfont"><mtext>&#x1D552;</mtext></math>=<span>1D552</span></span>
+ <span><math class="testfont"><mtext>&#x1D553;</mtext></math>=<span>1D553</span></span>
+ <span><math class="testfont"><mtext>&#x1D554;</mtext></math>=<span>1D554</span></span>
+ <span><math class="testfont"><mtext>&#x1D555;</mtext></math>=<span>1D555</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D556;</mtext></math>=<span>1D556</span></span>
+ <span><math class="testfont"><mtext>&#x1D557;</mtext></math>=<span>1D557</span></span>
+ <span><math class="testfont"><mtext>&#x1D558;</mtext></math>=<span>1D558</span></span>
+ <span><math class="testfont"><mtext>&#x1D559;</mtext></math>=<span>1D559</span></span>
+ <span><math class="testfont"><mtext>&#x1D55A;</mtext></math>=<span>1D55A</span></span>
+ <span><math class="testfont"><mtext>&#x1D55B;</mtext></math>=<span>1D55B</span></span>
+ <span><math class="testfont"><mtext>&#x1D55C;</mtext></math>=<span>1D55C</span></span>
+ <span><math class="testfont"><mtext>&#x1D55D;</mtext></math>=<span>1D55D</span></span>
+ <span><math class="testfont"><mtext>&#x1D55E;</mtext></math>=<span>1D55E</span></span>
+ <span><math class="testfont"><mtext>&#x1D55F;</mtext></math>=<span>1D55F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D560;</mtext></math>=<span>1D560</span></span>
+ <span><math class="testfont"><mtext>&#x1D561;</mtext></math>=<span>1D561</span></span>
+ <span><math class="testfont"><mtext>&#x1D562;</mtext></math>=<span>1D562</span></span>
+ <span><math class="testfont"><mtext>&#x1D563;</mtext></math>=<span>1D563</span></span>
+ <span><math class="testfont"><mtext>&#x1D564;</mtext></math>=<span>1D564</span></span>
+ <span><math class="testfont"><mtext>&#x1D565;</mtext></math>=<span>1D565</span></span>
+ <span><math class="testfont"><mtext>&#x1D566;</mtext></math>=<span>1D566</span></span>
+ <span><math class="testfont"><mtext>&#x1D567;</mtext></math>=<span>1D567</span></span>
+ <span><math class="testfont"><mtext>&#x1D568;</mtext></math>=<span>1D568</span></span>
+ <span><math class="testfont"><mtext>&#x1D569;</mtext></math>=<span>1D569</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D56A;</mtext></math>=<span>1D56A</span></span>
+ <span><math class="testfont"><mtext>&#x1D56B;</mtext></math>=<span>1D56B</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D8;</mtext></math>=<span>1D7D8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7D9;</mtext></math>=<span>1D7D9</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DA;</mtext></math>=<span>1D7DA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DB;</mtext></math>=<span>1D7DB</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DC;</mtext></math>=<span>1D7DC</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DD;</mtext></math>=<span>1D7DD</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DE;</mtext></math>=<span>1D7DE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7DF;</mtext></math>=<span>1D7DF</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7E0;</mtext></math>=<span>1D7E0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E1;</mtext></math>=<span>1D7E1</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA1;</mtext></math>=<span>1EEA1</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA2;</mtext></math>=<span>1EEA2</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA3;</mtext></math>=<span>1EEA3</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA5;</mtext></math>=<span>1EEA5</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA6;</mtext></math>=<span>1EEA6</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA7;</mtext></math>=<span>1EEA7</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA8;</mtext></math>=<span>1EEA8</span></span>
+ <span><math class="testfont"><mtext>&#x1EEA9;</mtext></math>=<span>1EEA9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EEAB;</mtext></math>=<span>1EEAB</span></span>
+ <span><math class="testfont"><mtext>&#x1EEAC;</mtext></math>=<span>1EEAC</span></span>
+ <span><math class="testfont"><mtext>&#x1EEAD;</mtext></math>=<span>1EEAD</span></span>
+ <span><math class="testfont"><mtext>&#x1EEAE;</mtext></math>=<span>1EEAE</span></span>
+ <span><math class="testfont"><mtext>&#x1EEAF;</mtext></math>=<span>1EEAF</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB0;</mtext></math>=<span>1EEB0</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB1;</mtext></math>=<span>1EEB1</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB2;</mtext></math>=<span>1EEB2</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB3;</mtext></math>=<span>1EEB3</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB4;</mtext></math>=<span>1EEB4</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EEB5;</mtext></math>=<span>1EEB5</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB6;</mtext></math>=<span>1EEB6</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB7;</mtext></math>=<span>1EEB7</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB8;</mtext></math>=<span>1EEB8</span></span>
+ <span><math class="testfont"><mtext>&#x1EEB9;</mtext></math>=<span>1EEB9</span></span>
+ <span><math class="testfont"><mtext>&#x1EEBA;</mtext></math>=<span>1EEBA</span></span>
+ <span><math class="testfont"><mtext>&#x1EEBB;</mtext></math>=<span>1EEBB</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck.html
new file mode 100644
index 0000000000..335234ac38
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-double-struck.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant double-struck</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#double-struck-mappings">
+<link rel="match" href="mathvariant-double-struck-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a double-struck mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x41;</mtext></math>=<span>1D538</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x42;</mtext></math>=<span>1D539</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x43;</mtext></math>=<span>02102</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x44;</mtext></math>=<span>1D53B</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x45;</mtext></math>=<span>1D53C</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x46;</mtext></math>=<span>1D53D</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x47;</mtext></math>=<span>1D53E</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x48;</mtext></math>=<span>0210D</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x49;</mtext></math>=<span>1D540</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4A;</mtext></math>=<span>1D541</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4B;</mtext></math>=<span>1D542</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4C;</mtext></math>=<span>1D543</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4D;</mtext></math>=<span>1D544</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4E;</mtext></math>=<span>02115</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x4F;</mtext></math>=<span>1D546</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x50;</mtext></math>=<span>02119</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x51;</mtext></math>=<span>0211A</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x52;</mtext></math>=<span>0211D</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x53;</mtext></math>=<span>1D54A</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x54;</mtext></math>=<span>1D54B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x55;</mtext></math>=<span>1D54C</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x56;</mtext></math>=<span>1D54D</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x57;</mtext></math>=<span>1D54E</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x58;</mtext></math>=<span>1D54F</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x59;</mtext></math>=<span>1D550</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x5A;</mtext></math>=<span>02124</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x61;</mtext></math>=<span>1D552</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62;</mtext></math>=<span>1D553</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x63;</mtext></math>=<span>1D554</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x64;</mtext></math>=<span>1D555</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x65;</mtext></math>=<span>1D556</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x66;</mtext></math>=<span>1D557</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x67;</mtext></math>=<span>1D558</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x68;</mtext></math>=<span>1D559</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x69;</mtext></math>=<span>1D55A</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6A;</mtext></math>=<span>1D55B</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6B;</mtext></math>=<span>1D55C</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6C;</mtext></math>=<span>1D55D</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6D;</mtext></math>=<span>1D55E</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6E;</mtext></math>=<span>1D55F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x6F;</mtext></math>=<span>1D560</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x70;</mtext></math>=<span>1D561</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x71;</mtext></math>=<span>1D562</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x72;</mtext></math>=<span>1D563</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x73;</mtext></math>=<span>1D564</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x74;</mtext></math>=<span>1D565</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x75;</mtext></math>=<span>1D566</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x76;</mtext></math>=<span>1D567</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x77;</mtext></math>=<span>1D568</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x78;</mtext></math>=<span>1D569</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x79;</mtext></math>=<span>1D56A</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x7A;</mtext></math>=<span>1D56B</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x30;</mtext></math>=<span>1D7D8</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x31;</mtext></math>=<span>1D7D9</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x32;</mtext></math>=<span>1D7DA</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x33;</mtext></math>=<span>1D7DB</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x34;</mtext></math>=<span>1D7DC</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x35;</mtext></math>=<span>1D7DD</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x36;</mtext></math>=<span>1D7DE</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x37;</mtext></math>=<span>1D7DF</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x38;</mtext></math>=<span>1D7E0</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x39;</mtext></math>=<span>1D7E1</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x628;</mtext></math>=<span>1EEA1</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62C;</mtext></math>=<span>1EEA2</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62F;</mtext></math>=<span>1EEA3</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x648;</mtext></math>=<span>1EEA5</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x632;</mtext></math>=<span>1EEA6</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62D;</mtext></math>=<span>1EEA7</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x637;</mtext></math>=<span>1EEA8</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x64A;</mtext></math>=<span>1EEA9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x644;</mtext></math>=<span>1EEAB</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x645;</mtext></math>=<span>1EEAC</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x646;</mtext></math>=<span>1EEAD</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x633;</mtext></math>=<span>1EEAE</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x639;</mtext></math>=<span>1EEAF</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x641;</mtext></math>=<span>1EEB0</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x635;</mtext></math>=<span>1EEB1</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x642;</mtext></math>=<span>1EEB2</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x631;</mtext></math>=<span>1EEB3</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x634;</mtext></math>=<span>1EEB4</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62A;</mtext></math>=<span>1EEB5</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62B;</mtext></math>=<span>1EEB6</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x62E;</mtext></math>=<span>1EEB7</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x630;</mtext></math>=<span>1EEB8</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x636;</mtext></math>=<span>1EEB9</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x638;</mtext></math>=<span>1EEBA</span></span>
+ <span><math class="testfont"><mtext mathvariant="double-struck">&#x63A;</mtext></math>=<span>1EEBB</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur-ref.html
new file mode 100644
index 0000000000..3d1dd50a7d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant fraktur (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D504;</mtext></math>=<span>1D504</span></span>
+ <span><math class="testfont"><mtext>&#x1D505;</mtext></math>=<span>1D505</span></span>
+ <span><math class="testfont"><mtext>&#x212D;</mtext></math>=<span>0212D</span></span>
+ <span><math class="testfont"><mtext>&#x1D507;</mtext></math>=<span>1D507</span></span>
+ <span><math class="testfont"><mtext>&#x1D508;</mtext></math>=<span>1D508</span></span>
+ <span><math class="testfont"><mtext>&#x1D509;</mtext></math>=<span>1D509</span></span>
+ <span><math class="testfont"><mtext>&#x1D50A;</mtext></math>=<span>1D50A</span></span>
+ <span><math class="testfont"><mtext>&#x210C;</mtext></math>=<span>0210C</span></span>
+ <span><math class="testfont"><mtext>&#x2111;</mtext></math>=<span>02111</span></span>
+ <span><math class="testfont"><mtext>&#x1D50D;</mtext></math>=<span>1D50D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D50E;</mtext></math>=<span>1D50E</span></span>
+ <span><math class="testfont"><mtext>&#x1D50F;</mtext></math>=<span>1D50F</span></span>
+ <span><math class="testfont"><mtext>&#x1D510;</mtext></math>=<span>1D510</span></span>
+ <span><math class="testfont"><mtext>&#x1D511;</mtext></math>=<span>1D511</span></span>
+ <span><math class="testfont"><mtext>&#x1D512;</mtext></math>=<span>1D512</span></span>
+ <span><math class="testfont"><mtext>&#x1D513;</mtext></math>=<span>1D513</span></span>
+ <span><math class="testfont"><mtext>&#x1D514;</mtext></math>=<span>1D514</span></span>
+ <span><math class="testfont"><mtext>&#x211C;</mtext></math>=<span>0211C</span></span>
+ <span><math class="testfont"><mtext>&#x1D516;</mtext></math>=<span>1D516</span></span>
+ <span><math class="testfont"><mtext>&#x1D517;</mtext></math>=<span>1D517</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D518;</mtext></math>=<span>1D518</span></span>
+ <span><math class="testfont"><mtext>&#x1D519;</mtext></math>=<span>1D519</span></span>
+ <span><math class="testfont"><mtext>&#x1D51A;</mtext></math>=<span>1D51A</span></span>
+ <span><math class="testfont"><mtext>&#x1D51B;</mtext></math>=<span>1D51B</span></span>
+ <span><math class="testfont"><mtext>&#x1D51C;</mtext></math>=<span>1D51C</span></span>
+ <span><math class="testfont"><mtext>&#x2128;</mtext></math>=<span>02128</span></span>
+ <span><math class="testfont"><mtext>&#x1D51E;</mtext></math>=<span>1D51E</span></span>
+ <span><math class="testfont"><mtext>&#x1D51F;</mtext></math>=<span>1D51F</span></span>
+ <span><math class="testfont"><mtext>&#x1D520;</mtext></math>=<span>1D520</span></span>
+ <span><math class="testfont"><mtext>&#x1D521;</mtext></math>=<span>1D521</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D522;</mtext></math>=<span>1D522</span></span>
+ <span><math class="testfont"><mtext>&#x1D523;</mtext></math>=<span>1D523</span></span>
+ <span><math class="testfont"><mtext>&#x1D524;</mtext></math>=<span>1D524</span></span>
+ <span><math class="testfont"><mtext>&#x1D525;</mtext></math>=<span>1D525</span></span>
+ <span><math class="testfont"><mtext>&#x1D526;</mtext></math>=<span>1D526</span></span>
+ <span><math class="testfont"><mtext>&#x1D527;</mtext></math>=<span>1D527</span></span>
+ <span><math class="testfont"><mtext>&#x1D528;</mtext></math>=<span>1D528</span></span>
+ <span><math class="testfont"><mtext>&#x1D529;</mtext></math>=<span>1D529</span></span>
+ <span><math class="testfont"><mtext>&#x1D52A;</mtext></math>=<span>1D52A</span></span>
+ <span><math class="testfont"><mtext>&#x1D52B;</mtext></math>=<span>1D52B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D52C;</mtext></math>=<span>1D52C</span></span>
+ <span><math class="testfont"><mtext>&#x1D52D;</mtext></math>=<span>1D52D</span></span>
+ <span><math class="testfont"><mtext>&#x1D52E;</mtext></math>=<span>1D52E</span></span>
+ <span><math class="testfont"><mtext>&#x1D52F;</mtext></math>=<span>1D52F</span></span>
+ <span><math class="testfont"><mtext>&#x1D530;</mtext></math>=<span>1D530</span></span>
+ <span><math class="testfont"><mtext>&#x1D531;</mtext></math>=<span>1D531</span></span>
+ <span><math class="testfont"><mtext>&#x1D532;</mtext></math>=<span>1D532</span></span>
+ <span><math class="testfont"><mtext>&#x1D533;</mtext></math>=<span>1D533</span></span>
+ <span><math class="testfont"><mtext>&#x1D534;</mtext></math>=<span>1D534</span></span>
+ <span><math class="testfont"><mtext>&#x1D535;</mtext></math>=<span>1D535</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D536;</mtext></math>=<span>1D536</span></span>
+ <span><math class="testfont"><mtext>&#x1D537;</mtext></math>=<span>1D537</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur.html
new file mode 100644
index 0000000000..9c95cd06e7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-fraktur.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant fraktur</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#fraktur-mappings">
+<link rel="match" href="mathvariant-fraktur-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a fraktur mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x41;</mtext></math>=<span>1D504</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x42;</mtext></math>=<span>1D505</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x43;</mtext></math>=<span>0212D</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x44;</mtext></math>=<span>1D507</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x45;</mtext></math>=<span>1D508</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x46;</mtext></math>=<span>1D509</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x47;</mtext></math>=<span>1D50A</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x48;</mtext></math>=<span>0210C</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x49;</mtext></math>=<span>02111</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4A;</mtext></math>=<span>1D50D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4B;</mtext></math>=<span>1D50E</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4C;</mtext></math>=<span>1D50F</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4D;</mtext></math>=<span>1D510</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4E;</mtext></math>=<span>1D511</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x4F;</mtext></math>=<span>1D512</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x50;</mtext></math>=<span>1D513</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x51;</mtext></math>=<span>1D514</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x52;</mtext></math>=<span>0211C</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x53;</mtext></math>=<span>1D516</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x54;</mtext></math>=<span>1D517</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x55;</mtext></math>=<span>1D518</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x56;</mtext></math>=<span>1D519</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x57;</mtext></math>=<span>1D51A</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x58;</mtext></math>=<span>1D51B</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x59;</mtext></math>=<span>1D51C</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x5A;</mtext></math>=<span>02128</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x61;</mtext></math>=<span>1D51E</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x62;</mtext></math>=<span>1D51F</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x63;</mtext></math>=<span>1D520</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x64;</mtext></math>=<span>1D521</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x65;</mtext></math>=<span>1D522</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x66;</mtext></math>=<span>1D523</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x67;</mtext></math>=<span>1D524</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x68;</mtext></math>=<span>1D525</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x69;</mtext></math>=<span>1D526</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6A;</mtext></math>=<span>1D527</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6B;</mtext></math>=<span>1D528</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6C;</mtext></math>=<span>1D529</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6D;</mtext></math>=<span>1D52A</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6E;</mtext></math>=<span>1D52B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x6F;</mtext></math>=<span>1D52C</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x70;</mtext></math>=<span>1D52D</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x71;</mtext></math>=<span>1D52E</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x72;</mtext></math>=<span>1D52F</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x73;</mtext></math>=<span>1D530</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x74;</mtext></math>=<span>1D531</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x75;</mtext></math>=<span>1D532</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x76;</mtext></math>=<span>1D533</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x77;</mtext></math>=<span>1D534</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x78;</mtext></math>=<span>1D535</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x79;</mtext></math>=<span>1D536</span></span>
+ <span><math class="testfont"><mtext mathvariant="fraktur">&#x7A;</mtext></math>=<span>1D537</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial-ref.html
new file mode 100644
index 0000000000..5d5b72a1c5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial-ref.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant initial (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1EE21;</mtext></math>=<span>1EE21</span></span>
+ <span><math class="testfont"><mtext>&#x1EE22;</mtext></math>=<span>1EE22</span></span>
+ <span><math class="testfont"><mtext>&#x1EE24;</mtext></math>=<span>1EE24</span></span>
+ <span><math class="testfont"><mtext>&#x1EE27;</mtext></math>=<span>1EE27</span></span>
+ <span><math class="testfont"><mtext>&#x1EE29;</mtext></math>=<span>1EE29</span></span>
+ <span><math class="testfont"><mtext>&#x1EE2A;</mtext></math>=<span>1EE2A</span></span>
+ <span><math class="testfont"><mtext>&#x1EE2B;</mtext></math>=<span>1EE2B</span></span>
+ <span><math class="testfont"><mtext>&#x1EE2C;</mtext></math>=<span>1EE2C</span></span>
+ <span><math class="testfont"><mtext>&#x1EE2D;</mtext></math>=<span>1EE2D</span></span>
+ <span><math class="testfont"><mtext>&#x1EE2E;</mtext></math>=<span>1EE2E</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE2F;</mtext></math>=<span>1EE2F</span></span>
+ <span><math class="testfont"><mtext>&#x1EE30;</mtext></math>=<span>1EE30</span></span>
+ <span><math class="testfont"><mtext>&#x1EE31;</mtext></math>=<span>1EE31</span></span>
+ <span><math class="testfont"><mtext>&#x1EE32;</mtext></math>=<span>1EE32</span></span>
+ <span><math class="testfont"><mtext>&#x1EE34;</mtext></math>=<span>1EE34</span></span>
+ <span><math class="testfont"><mtext>&#x1EE35;</mtext></math>=<span>1EE35</span></span>
+ <span><math class="testfont"><mtext>&#x1EE36;</mtext></math>=<span>1EE36</span></span>
+ <span><math class="testfont"><mtext>&#x1EE37;</mtext></math>=<span>1EE37</span></span>
+ <span><math class="testfont"><mtext>&#x1EE39;</mtext></math>=<span>1EE39</span></span>
+ <span><math class="testfont"><mtext>&#x1EE3B;</mtext></math>=<span>1EE3B</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial.html
new file mode 100644
index 0000000000..3b0263a197
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-initial.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant initial</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#initial-mappings">
+<link rel="match" href="mathvariant-initial-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a initial mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x628;</mtext></math>=<span>1EE21</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x62C;</mtext></math>=<span>1EE22</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x647;</mtext></math>=<span>1EE24</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x62D;</mtext></math>=<span>1EE27</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x64A;</mtext></math>=<span>1EE29</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x643;</mtext></math>=<span>1EE2A</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x644;</mtext></math>=<span>1EE2B</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x645;</mtext></math>=<span>1EE2C</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x646;</mtext></math>=<span>1EE2D</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x633;</mtext></math>=<span>1EE2E</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x639;</mtext></math>=<span>1EE2F</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x641;</mtext></math>=<span>1EE30</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x635;</mtext></math>=<span>1EE31</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x642;</mtext></math>=<span>1EE32</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x634;</mtext></math>=<span>1EE34</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x62A;</mtext></math>=<span>1EE35</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x62B;</mtext></math>=<span>1EE36</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x62E;</mtext></math>=<span>1EE37</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x636;</mtext></math>=<span>1EE39</span></span>
+ <span><math class="testfont"><mtext mathvariant="initial">&#x63A;</mtext></math>=<span>1EE3B</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic-ref.html
new file mode 100644
index 0000000000..e2078c2948
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic-ref.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant italic (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D434;</mtext></math>=<span>1D434</span></span>
+ <span><math class="testfont"><mtext>&#x1D435;</mtext></math>=<span>1D435</span></span>
+ <span><math class="testfont"><mtext>&#x1D436;</mtext></math>=<span>1D436</span></span>
+ <span><math class="testfont"><mtext>&#x1D437;</mtext></math>=<span>1D437</span></span>
+ <span><math class="testfont"><mtext>&#x1D438;</mtext></math>=<span>1D438</span></span>
+ <span><math class="testfont"><mtext>&#x1D439;</mtext></math>=<span>1D439</span></span>
+ <span><math class="testfont"><mtext>&#x1D43A;</mtext></math>=<span>1D43A</span></span>
+ <span><math class="testfont"><mtext>&#x1D43B;</mtext></math>=<span>1D43B</span></span>
+ <span><math class="testfont"><mtext>&#x1D43C;</mtext></math>=<span>1D43C</span></span>
+ <span><math class="testfont"><mtext>&#x1D43D;</mtext></math>=<span>1D43D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D43E;</mtext></math>=<span>1D43E</span></span>
+ <span><math class="testfont"><mtext>&#x1D43F;</mtext></math>=<span>1D43F</span></span>
+ <span><math class="testfont"><mtext>&#x1D440;</mtext></math>=<span>1D440</span></span>
+ <span><math class="testfont"><mtext>&#x1D441;</mtext></math>=<span>1D441</span></span>
+ <span><math class="testfont"><mtext>&#x1D442;</mtext></math>=<span>1D442</span></span>
+ <span><math class="testfont"><mtext>&#x1D443;</mtext></math>=<span>1D443</span></span>
+ <span><math class="testfont"><mtext>&#x1D444;</mtext></math>=<span>1D444</span></span>
+ <span><math class="testfont"><mtext>&#x1D445;</mtext></math>=<span>1D445</span></span>
+ <span><math class="testfont"><mtext>&#x1D446;</mtext></math>=<span>1D446</span></span>
+ <span><math class="testfont"><mtext>&#x1D447;</mtext></math>=<span>1D447</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D448;</mtext></math>=<span>1D448</span></span>
+ <span><math class="testfont"><mtext>&#x1D449;</mtext></math>=<span>1D449</span></span>
+ <span><math class="testfont"><mtext>&#x1D44A;</mtext></math>=<span>1D44A</span></span>
+ <span><math class="testfont"><mtext>&#x1D44B;</mtext></math>=<span>1D44B</span></span>
+ <span><math class="testfont"><mtext>&#x1D44C;</mtext></math>=<span>1D44C</span></span>
+ <span><math class="testfont"><mtext>&#x1D44D;</mtext></math>=<span>1D44D</span></span>
+ <span><math class="testfont"><mtext>&#x1D44E;</mtext></math>=<span>1D44E</span></span>
+ <span><math class="testfont"><mtext>&#x1D44F;</mtext></math>=<span>1D44F</span></span>
+ <span><math class="testfont"><mtext>&#x1D450;</mtext></math>=<span>1D450</span></span>
+ <span><math class="testfont"><mtext>&#x1D451;</mtext></math>=<span>1D451</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D452;</mtext></math>=<span>1D452</span></span>
+ <span><math class="testfont"><mtext>&#x1D453;</mtext></math>=<span>1D453</span></span>
+ <span><math class="testfont"><mtext>&#x1D454;</mtext></math>=<span>1D454</span></span>
+ <span><math class="testfont"><mtext>&#x210E;</mtext></math>=<span>0210E</span></span>
+ <span><math class="testfont"><mtext>&#x1D456;</mtext></math>=<span>1D456</span></span>
+ <span><math class="testfont"><mtext>&#x1D457;</mtext></math>=<span>1D457</span></span>
+ <span><math class="testfont"><mtext>&#x1D458;</mtext></math>=<span>1D458</span></span>
+ <span><math class="testfont"><mtext>&#x1D459;</mtext></math>=<span>1D459</span></span>
+ <span><math class="testfont"><mtext>&#x1D45A;</mtext></math>=<span>1D45A</span></span>
+ <span><math class="testfont"><mtext>&#x1D45B;</mtext></math>=<span>1D45B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D45C;</mtext></math>=<span>1D45C</span></span>
+ <span><math class="testfont"><mtext>&#x1D45D;</mtext></math>=<span>1D45D</span></span>
+ <span><math class="testfont"><mtext>&#x1D45E;</mtext></math>=<span>1D45E</span></span>
+ <span><math class="testfont"><mtext>&#x1D45F;</mtext></math>=<span>1D45F</span></span>
+ <span><math class="testfont"><mtext>&#x1D460;</mtext></math>=<span>1D460</span></span>
+ <span><math class="testfont"><mtext>&#x1D461;</mtext></math>=<span>1D461</span></span>
+ <span><math class="testfont"><mtext>&#x1D462;</mtext></math>=<span>1D462</span></span>
+ <span><math class="testfont"><mtext>&#x1D463;</mtext></math>=<span>1D463</span></span>
+ <span><math class="testfont"><mtext>&#x1D464;</mtext></math>=<span>1D464</span></span>
+ <span><math class="testfont"><mtext>&#x1D465;</mtext></math>=<span>1D465</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D466;</mtext></math>=<span>1D466</span></span>
+ <span><math class="testfont"><mtext>&#x1D467;</mtext></math>=<span>1D467</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A4;</mtext></math>=<span>1D6A4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A5;</mtext></math>=<span>1D6A5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E2;</mtext></math>=<span>1D6E2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E3;</mtext></math>=<span>1D6E3</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E4;</mtext></math>=<span>1D6E4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E5;</mtext></math>=<span>1D6E5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E6;</mtext></math>=<span>1D6E6</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E7;</mtext></math>=<span>1D6E7</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6E8;</mtext></math>=<span>1D6E8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6E9;</mtext></math>=<span>1D6E9</span></span>
+ <span><math class="testfont"><mtext>&#x1D6EA;</mtext></math>=<span>1D6EA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6EB;</mtext></math>=<span>1D6EB</span></span>
+ <span><math class="testfont"><mtext>&#x1D6EC;</mtext></math>=<span>1D6EC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6ED;</mtext></math>=<span>1D6ED</span></span>
+ <span><math class="testfont"><mtext>&#x1D6EE;</mtext></math>=<span>1D6EE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6EF;</mtext></math>=<span>1D6EF</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F0;</mtext></math>=<span>1D6F0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F1;</mtext></math>=<span>1D6F1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6F2;</mtext></math>=<span>1D6F2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F3;</mtext></math>=<span>1D6F3</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F4;</mtext></math>=<span>1D6F4</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F5;</mtext></math>=<span>1D6F5</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F6;</mtext></math>=<span>1D6F6</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F7;</mtext></math>=<span>1D6F7</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F8;</mtext></math>=<span>1D6F8</span></span>
+ <span><math class="testfont"><mtext>&#x1D6F9;</mtext></math>=<span>1D6F9</span></span>
+ <span><math class="testfont"><mtext>&#x1D6FA;</mtext></math>=<span>1D6FA</span></span>
+ <span><math class="testfont"><mtext>&#x1D6FB;</mtext></math>=<span>1D6FB</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6FC;</mtext></math>=<span>1D6FC</span></span>
+ <span><math class="testfont"><mtext>&#x1D6FD;</mtext></math>=<span>1D6FD</span></span>
+ <span><math class="testfont"><mtext>&#x1D6FE;</mtext></math>=<span>1D6FE</span></span>
+ <span><math class="testfont"><mtext>&#x1D6FF;</mtext></math>=<span>1D6FF</span></span>
+ <span><math class="testfont"><mtext>&#x1D700;</mtext></math>=<span>1D700</span></span>
+ <span><math class="testfont"><mtext>&#x1D701;</mtext></math>=<span>1D701</span></span>
+ <span><math class="testfont"><mtext>&#x1D702;</mtext></math>=<span>1D702</span></span>
+ <span><math class="testfont"><mtext>&#x1D703;</mtext></math>=<span>1D703</span></span>
+ <span><math class="testfont"><mtext>&#x1D704;</mtext></math>=<span>1D704</span></span>
+ <span><math class="testfont"><mtext>&#x1D705;</mtext></math>=<span>1D705</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D706;</mtext></math>=<span>1D706</span></span>
+ <span><math class="testfont"><mtext>&#x1D707;</mtext></math>=<span>1D707</span></span>
+ <span><math class="testfont"><mtext>&#x1D708;</mtext></math>=<span>1D708</span></span>
+ <span><math class="testfont"><mtext>&#x1D709;</mtext></math>=<span>1D709</span></span>
+ <span><math class="testfont"><mtext>&#x1D70A;</mtext></math>=<span>1D70A</span></span>
+ <span><math class="testfont"><mtext>&#x1D70B;</mtext></math>=<span>1D70B</span></span>
+ <span><math class="testfont"><mtext>&#x1D70C;</mtext></math>=<span>1D70C</span></span>
+ <span><math class="testfont"><mtext>&#x1D70D;</mtext></math>=<span>1D70D</span></span>
+ <span><math class="testfont"><mtext>&#x1D70E;</mtext></math>=<span>1D70E</span></span>
+ <span><math class="testfont"><mtext>&#x1D70F;</mtext></math>=<span>1D70F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D710;</mtext></math>=<span>1D710</span></span>
+ <span><math class="testfont"><mtext>&#x1D711;</mtext></math>=<span>1D711</span></span>
+ <span><math class="testfont"><mtext>&#x1D712;</mtext></math>=<span>1D712</span></span>
+ <span><math class="testfont"><mtext>&#x1D713;</mtext></math>=<span>1D713</span></span>
+ <span><math class="testfont"><mtext>&#x1D714;</mtext></math>=<span>1D714</span></span>
+ <span><math class="testfont"><mtext>&#x1D715;</mtext></math>=<span>1D715</span></span>
+ <span><math class="testfont"><mtext>&#x1D716;</mtext></math>=<span>1D716</span></span>
+ <span><math class="testfont"><mtext>&#x1D717;</mtext></math>=<span>1D717</span></span>
+ <span><math class="testfont"><mtext>&#x1D718;</mtext></math>=<span>1D718</span></span>
+ <span><math class="testfont"><mtext>&#x1D719;</mtext></math>=<span>1D719</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D71A;</mtext></math>=<span>1D71A</span></span>
+ <span><math class="testfont"><mtext>&#x1D71B;</mtext></math>=<span>1D71B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic.html
new file mode 100644
index 0000000000..1e6aa6512d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-italic.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant italic</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#italic-mappings">
+<link rel="match" href="mathvariant-italic-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x41;</mtext></math>=<span>1D434</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x42;</mtext></math>=<span>1D435</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x43;</mtext></math>=<span>1D436</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x44;</mtext></math>=<span>1D437</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x45;</mtext></math>=<span>1D438</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x46;</mtext></math>=<span>1D439</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x47;</mtext></math>=<span>1D43A</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x48;</mtext></math>=<span>1D43B</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x49;</mtext></math>=<span>1D43C</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4A;</mtext></math>=<span>1D43D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4B;</mtext></math>=<span>1D43E</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4C;</mtext></math>=<span>1D43F</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4D;</mtext></math>=<span>1D440</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4E;</mtext></math>=<span>1D441</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x4F;</mtext></math>=<span>1D442</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x50;</mtext></math>=<span>1D443</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x51;</mtext></math>=<span>1D444</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x52;</mtext></math>=<span>1D445</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x53;</mtext></math>=<span>1D446</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x54;</mtext></math>=<span>1D447</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x55;</mtext></math>=<span>1D448</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x56;</mtext></math>=<span>1D449</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x57;</mtext></math>=<span>1D44A</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x58;</mtext></math>=<span>1D44B</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x59;</mtext></math>=<span>1D44C</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x5A;</mtext></math>=<span>1D44D</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x61;</mtext></math>=<span>1D44E</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x62;</mtext></math>=<span>1D44F</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x63;</mtext></math>=<span>1D450</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x64;</mtext></math>=<span>1D451</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x65;</mtext></math>=<span>1D452</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x66;</mtext></math>=<span>1D453</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x67;</mtext></math>=<span>1D454</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x68;</mtext></math>=<span>0210E</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x69;</mtext></math>=<span>1D456</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6A;</mtext></math>=<span>1D457</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6B;</mtext></math>=<span>1D458</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6C;</mtext></math>=<span>1D459</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6D;</mtext></math>=<span>1D45A</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6E;</mtext></math>=<span>1D45B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x6F;</mtext></math>=<span>1D45C</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x70;</mtext></math>=<span>1D45D</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x71;</mtext></math>=<span>1D45E</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x72;</mtext></math>=<span>1D45F</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x73;</mtext></math>=<span>1D460</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x74;</mtext></math>=<span>1D461</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x75;</mtext></math>=<span>1D462</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x76;</mtext></math>=<span>1D463</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x77;</mtext></math>=<span>1D464</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x78;</mtext></math>=<span>1D465</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x79;</mtext></math>=<span>1D466</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x7A;</mtext></math>=<span>1D467</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x131;</mtext></math>=<span>1D6A4</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x237;</mtext></math>=<span>1D6A5</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x391;</mtext></math>=<span>1D6E2</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x392;</mtext></math>=<span>1D6E3</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x393;</mtext></math>=<span>1D6E4</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x394;</mtext></math>=<span>1D6E5</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x395;</mtext></math>=<span>1D6E6</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x396;</mtext></math>=<span>1D6E7</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x397;</mtext></math>=<span>1D6E8</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x398;</mtext></math>=<span>1D6E9</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x399;</mtext></math>=<span>1D6EA</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39A;</mtext></math>=<span>1D6EB</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39B;</mtext></math>=<span>1D6EC</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39C;</mtext></math>=<span>1D6ED</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39D;</mtext></math>=<span>1D6EE</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39E;</mtext></math>=<span>1D6EF</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x39F;</mtext></math>=<span>1D6F0</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A0;</mtext></math>=<span>1D6F1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A1;</mtext></math>=<span>1D6F2</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3F4;</mtext></math>=<span>1D6F3</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A3;</mtext></math>=<span>1D6F4</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A4;</mtext></math>=<span>1D6F5</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A5;</mtext></math>=<span>1D6F6</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A6;</mtext></math>=<span>1D6F7</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A7;</mtext></math>=<span>1D6F8</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A8;</mtext></math>=<span>1D6F9</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3A9;</mtext></math>=<span>1D6FA</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x2207;</mtext></math>=<span>1D6FB</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B1;</mtext></math>=<span>1D6FC</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B2;</mtext></math>=<span>1D6FD</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B3;</mtext></math>=<span>1D6FE</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B4;</mtext></math>=<span>1D6FF</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B5;</mtext></math>=<span>1D700</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B6;</mtext></math>=<span>1D701</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B7;</mtext></math>=<span>1D702</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B8;</mtext></math>=<span>1D703</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3B9;</mtext></math>=<span>1D704</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BA;</mtext></math>=<span>1D705</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BB;</mtext></math>=<span>1D706</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BC;</mtext></math>=<span>1D707</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BD;</mtext></math>=<span>1D708</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BE;</mtext></math>=<span>1D709</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3BF;</mtext></math>=<span>1D70A</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C0;</mtext></math>=<span>1D70B</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C1;</mtext></math>=<span>1D70C</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C2;</mtext></math>=<span>1D70D</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C3;</mtext></math>=<span>1D70E</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C4;</mtext></math>=<span>1D70F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C5;</mtext></math>=<span>1D710</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C6;</mtext></math>=<span>1D711</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C7;</mtext></math>=<span>1D712</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C8;</mtext></math>=<span>1D713</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3C9;</mtext></math>=<span>1D714</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x2202;</mtext></math>=<span>1D715</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3F5;</mtext></math>=<span>1D716</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3D1;</mtext></math>=<span>1D717</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3F0;</mtext></math>=<span>1D718</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3D5;</mtext></math>=<span>1D719</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3F1;</mtext></math>=<span>1D71A</span></span>
+ <span><math class="testfont"><mtext mathvariant="italic">&#x3D6;</mtext></math>=<span>1D71B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped-ref.html
new file mode 100644
index 0000000000..f00e5d87bb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant looped (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1EE80;</mtext></math>=<span>1EE80</span></span>
+ <span><math class="testfont"><mtext>&#x1EE81;</mtext></math>=<span>1EE81</span></span>
+ <span><math class="testfont"><mtext>&#x1EE82;</mtext></math>=<span>1EE82</span></span>
+ <span><math class="testfont"><mtext>&#x1EE83;</mtext></math>=<span>1EE83</span></span>
+ <span><math class="testfont"><mtext>&#x1EE84;</mtext></math>=<span>1EE84</span></span>
+ <span><math class="testfont"><mtext>&#x1EE85;</mtext></math>=<span>1EE85</span></span>
+ <span><math class="testfont"><mtext>&#x1EE86;</mtext></math>=<span>1EE86</span></span>
+ <span><math class="testfont"><mtext>&#x1EE87;</mtext></math>=<span>1EE87</span></span>
+ <span><math class="testfont"><mtext>&#x1EE88;</mtext></math>=<span>1EE88</span></span>
+ <span><math class="testfont"><mtext>&#x1EE89;</mtext></math>=<span>1EE89</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE8B;</mtext></math>=<span>1EE8B</span></span>
+ <span><math class="testfont"><mtext>&#x1EE8C;</mtext></math>=<span>1EE8C</span></span>
+ <span><math class="testfont"><mtext>&#x1EE8D;</mtext></math>=<span>1EE8D</span></span>
+ <span><math class="testfont"><mtext>&#x1EE8E;</mtext></math>=<span>1EE8E</span></span>
+ <span><math class="testfont"><mtext>&#x1EE8F;</mtext></math>=<span>1EE8F</span></span>
+ <span><math class="testfont"><mtext>&#x1EE90;</mtext></math>=<span>1EE90</span></span>
+ <span><math class="testfont"><mtext>&#x1EE91;</mtext></math>=<span>1EE91</span></span>
+ <span><math class="testfont"><mtext>&#x1EE92;</mtext></math>=<span>1EE92</span></span>
+ <span><math class="testfont"><mtext>&#x1EE93;</mtext></math>=<span>1EE93</span></span>
+ <span><math class="testfont"><mtext>&#x1EE94;</mtext></math>=<span>1EE94</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE95;</mtext></math>=<span>1EE95</span></span>
+ <span><math class="testfont"><mtext>&#x1EE96;</mtext></math>=<span>1EE96</span></span>
+ <span><math class="testfont"><mtext>&#x1EE97;</mtext></math>=<span>1EE97</span></span>
+ <span><math class="testfont"><mtext>&#x1EE98;</mtext></math>=<span>1EE98</span></span>
+ <span><math class="testfont"><mtext>&#x1EE99;</mtext></math>=<span>1EE99</span></span>
+ <span><math class="testfont"><mtext>&#x1EE9A;</mtext></math>=<span>1EE9A</span></span>
+ <span><math class="testfont"><mtext>&#x1EE9B;</mtext></math>=<span>1EE9B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped.html
new file mode 100644
index 0000000000..b208849368
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-looped.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant looped</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#looped-mappings">
+<link rel="match" href="mathvariant-looped-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a looped mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x627;</mtext></math>=<span>1EE80</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x628;</mtext></math>=<span>1EE81</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62C;</mtext></math>=<span>1EE82</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62F;</mtext></math>=<span>1EE83</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x647;</mtext></math>=<span>1EE84</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x648;</mtext></math>=<span>1EE85</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x632;</mtext></math>=<span>1EE86</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62D;</mtext></math>=<span>1EE87</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x637;</mtext></math>=<span>1EE88</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x64A;</mtext></math>=<span>1EE89</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x644;</mtext></math>=<span>1EE8B</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x645;</mtext></math>=<span>1EE8C</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x646;</mtext></math>=<span>1EE8D</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x633;</mtext></math>=<span>1EE8E</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x639;</mtext></math>=<span>1EE8F</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x641;</mtext></math>=<span>1EE90</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x635;</mtext></math>=<span>1EE91</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x642;</mtext></math>=<span>1EE92</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x631;</mtext></math>=<span>1EE93</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x634;</mtext></math>=<span>1EE94</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62A;</mtext></math>=<span>1EE95</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62B;</mtext></math>=<span>1EE96</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x62E;</mtext></math>=<span>1EE97</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x630;</mtext></math>=<span>1EE98</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x636;</mtext></math>=<span>1EE99</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x638;</mtext></math>=<span>1EE9A</span></span>
+ <span><math class="testfont"><mtext mathvariant="looped">&#x63A;</mtext></math>=<span>1EE9B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace-ref.html
new file mode 100644
index 0000000000..1d4a0c0a52
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace-ref.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant monospace (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D670;</mtext></math>=<span>1D670</span></span>
+ <span><math class="testfont"><mtext>&#x1D671;</mtext></math>=<span>1D671</span></span>
+ <span><math class="testfont"><mtext>&#x1D672;</mtext></math>=<span>1D672</span></span>
+ <span><math class="testfont"><mtext>&#x1D673;</mtext></math>=<span>1D673</span></span>
+ <span><math class="testfont"><mtext>&#x1D674;</mtext></math>=<span>1D674</span></span>
+ <span><math class="testfont"><mtext>&#x1D675;</mtext></math>=<span>1D675</span></span>
+ <span><math class="testfont"><mtext>&#x1D676;</mtext></math>=<span>1D676</span></span>
+ <span><math class="testfont"><mtext>&#x1D677;</mtext></math>=<span>1D677</span></span>
+ <span><math class="testfont"><mtext>&#x1D678;</mtext></math>=<span>1D678</span></span>
+ <span><math class="testfont"><mtext>&#x1D679;</mtext></math>=<span>1D679</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D67A;</mtext></math>=<span>1D67A</span></span>
+ <span><math class="testfont"><mtext>&#x1D67B;</mtext></math>=<span>1D67B</span></span>
+ <span><math class="testfont"><mtext>&#x1D67C;</mtext></math>=<span>1D67C</span></span>
+ <span><math class="testfont"><mtext>&#x1D67D;</mtext></math>=<span>1D67D</span></span>
+ <span><math class="testfont"><mtext>&#x1D67E;</mtext></math>=<span>1D67E</span></span>
+ <span><math class="testfont"><mtext>&#x1D67F;</mtext></math>=<span>1D67F</span></span>
+ <span><math class="testfont"><mtext>&#x1D680;</mtext></math>=<span>1D680</span></span>
+ <span><math class="testfont"><mtext>&#x1D681;</mtext></math>=<span>1D681</span></span>
+ <span><math class="testfont"><mtext>&#x1D682;</mtext></math>=<span>1D682</span></span>
+ <span><math class="testfont"><mtext>&#x1D683;</mtext></math>=<span>1D683</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D684;</mtext></math>=<span>1D684</span></span>
+ <span><math class="testfont"><mtext>&#x1D685;</mtext></math>=<span>1D685</span></span>
+ <span><math class="testfont"><mtext>&#x1D686;</mtext></math>=<span>1D686</span></span>
+ <span><math class="testfont"><mtext>&#x1D687;</mtext></math>=<span>1D687</span></span>
+ <span><math class="testfont"><mtext>&#x1D688;</mtext></math>=<span>1D688</span></span>
+ <span><math class="testfont"><mtext>&#x1D689;</mtext></math>=<span>1D689</span></span>
+ <span><math class="testfont"><mtext>&#x1D68A;</mtext></math>=<span>1D68A</span></span>
+ <span><math class="testfont"><mtext>&#x1D68B;</mtext></math>=<span>1D68B</span></span>
+ <span><math class="testfont"><mtext>&#x1D68C;</mtext></math>=<span>1D68C</span></span>
+ <span><math class="testfont"><mtext>&#x1D68D;</mtext></math>=<span>1D68D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D68E;</mtext></math>=<span>1D68E</span></span>
+ <span><math class="testfont"><mtext>&#x1D68F;</mtext></math>=<span>1D68F</span></span>
+ <span><math class="testfont"><mtext>&#x1D690;</mtext></math>=<span>1D690</span></span>
+ <span><math class="testfont"><mtext>&#x1D691;</mtext></math>=<span>1D691</span></span>
+ <span><math class="testfont"><mtext>&#x1D692;</mtext></math>=<span>1D692</span></span>
+ <span><math class="testfont"><mtext>&#x1D693;</mtext></math>=<span>1D693</span></span>
+ <span><math class="testfont"><mtext>&#x1D694;</mtext></math>=<span>1D694</span></span>
+ <span><math class="testfont"><mtext>&#x1D695;</mtext></math>=<span>1D695</span></span>
+ <span><math class="testfont"><mtext>&#x1D696;</mtext></math>=<span>1D696</span></span>
+ <span><math class="testfont"><mtext>&#x1D697;</mtext></math>=<span>1D697</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D698;</mtext></math>=<span>1D698</span></span>
+ <span><math class="testfont"><mtext>&#x1D699;</mtext></math>=<span>1D699</span></span>
+ <span><math class="testfont"><mtext>&#x1D69A;</mtext></math>=<span>1D69A</span></span>
+ <span><math class="testfont"><mtext>&#x1D69B;</mtext></math>=<span>1D69B</span></span>
+ <span><math class="testfont"><mtext>&#x1D69C;</mtext></math>=<span>1D69C</span></span>
+ <span><math class="testfont"><mtext>&#x1D69D;</mtext></math>=<span>1D69D</span></span>
+ <span><math class="testfont"><mtext>&#x1D69E;</mtext></math>=<span>1D69E</span></span>
+ <span><math class="testfont"><mtext>&#x1D69F;</mtext></math>=<span>1D69F</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A0;</mtext></math>=<span>1D6A0</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A1;</mtext></math>=<span>1D6A1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D6A2;</mtext></math>=<span>1D6A2</span></span>
+ <span><math class="testfont"><mtext>&#x1D6A3;</mtext></math>=<span>1D6A3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F6;</mtext></math>=<span>1D7F6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F7;</mtext></math>=<span>1D7F7</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F8;</mtext></math>=<span>1D7F8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7F9;</mtext></math>=<span>1D7F9</span></span>
+ <span><math class="testfont"><mtext>&#x1D7FA;</mtext></math>=<span>1D7FA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7FB;</mtext></math>=<span>1D7FB</span></span>
+ <span><math class="testfont"><mtext>&#x1D7FC;</mtext></math>=<span>1D7FC</span></span>
+ <span><math class="testfont"><mtext>&#x1D7FD;</mtext></math>=<span>1D7FD</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7FE;</mtext></math>=<span>1D7FE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7FF;</mtext></math>=<span>1D7FF</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace.html
new file mode 100644
index 0000000000..ad5541fe0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-monospace.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant monospace</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#monospace-mappings">
+<link rel="match" href="mathvariant-monospace-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a monospace mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x41;</mtext></math>=<span>1D670</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x42;</mtext></math>=<span>1D671</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x43;</mtext></math>=<span>1D672</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x44;</mtext></math>=<span>1D673</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x45;</mtext></math>=<span>1D674</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x46;</mtext></math>=<span>1D675</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x47;</mtext></math>=<span>1D676</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x48;</mtext></math>=<span>1D677</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x49;</mtext></math>=<span>1D678</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4A;</mtext></math>=<span>1D679</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4B;</mtext></math>=<span>1D67A</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4C;</mtext></math>=<span>1D67B</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4D;</mtext></math>=<span>1D67C</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4E;</mtext></math>=<span>1D67D</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x4F;</mtext></math>=<span>1D67E</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x50;</mtext></math>=<span>1D67F</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x51;</mtext></math>=<span>1D680</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x52;</mtext></math>=<span>1D681</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x53;</mtext></math>=<span>1D682</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x54;</mtext></math>=<span>1D683</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x55;</mtext></math>=<span>1D684</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x56;</mtext></math>=<span>1D685</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x57;</mtext></math>=<span>1D686</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x58;</mtext></math>=<span>1D687</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x59;</mtext></math>=<span>1D688</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x5A;</mtext></math>=<span>1D689</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x61;</mtext></math>=<span>1D68A</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x62;</mtext></math>=<span>1D68B</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x63;</mtext></math>=<span>1D68C</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x64;</mtext></math>=<span>1D68D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x65;</mtext></math>=<span>1D68E</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x66;</mtext></math>=<span>1D68F</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x67;</mtext></math>=<span>1D690</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x68;</mtext></math>=<span>1D691</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x69;</mtext></math>=<span>1D692</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6A;</mtext></math>=<span>1D693</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6B;</mtext></math>=<span>1D694</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6C;</mtext></math>=<span>1D695</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6D;</mtext></math>=<span>1D696</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6E;</mtext></math>=<span>1D697</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x6F;</mtext></math>=<span>1D698</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x70;</mtext></math>=<span>1D699</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x71;</mtext></math>=<span>1D69A</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x72;</mtext></math>=<span>1D69B</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x73;</mtext></math>=<span>1D69C</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x74;</mtext></math>=<span>1D69D</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x75;</mtext></math>=<span>1D69E</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x76;</mtext></math>=<span>1D69F</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x77;</mtext></math>=<span>1D6A0</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x78;</mtext></math>=<span>1D6A1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x79;</mtext></math>=<span>1D6A2</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x7A;</mtext></math>=<span>1D6A3</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x30;</mtext></math>=<span>1D7F6</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x31;</mtext></math>=<span>1D7F7</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x32;</mtext></math>=<span>1D7F8</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x33;</mtext></math>=<span>1D7F9</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x34;</mtext></math>=<span>1D7FA</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x35;</mtext></math>=<span>1D7FB</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x36;</mtext></math>=<span>1D7FC</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x37;</mtext></math>=<span>1D7FD</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x38;</mtext></math>=<span>1D7FE</span></span>
+ <span><math class="testfont"><mtext mathvariant="monospace">&#x39;</mtext></math>=<span>1D7FF</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic-ref.html
new file mode 100644
index 0000000000..f918db9b48
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic-ref.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif-bold-italic (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D63C;</mtext></math>=<span>1D63C</span></span>
+ <span><math class="testfont"><mtext>&#x1D63D;</mtext></math>=<span>1D63D</span></span>
+ <span><math class="testfont"><mtext>&#x1D63E;</mtext></math>=<span>1D63E</span></span>
+ <span><math class="testfont"><mtext>&#x1D63F;</mtext></math>=<span>1D63F</span></span>
+ <span><math class="testfont"><mtext>&#x1D640;</mtext></math>=<span>1D640</span></span>
+ <span><math class="testfont"><mtext>&#x1D641;</mtext></math>=<span>1D641</span></span>
+ <span><math class="testfont"><mtext>&#x1D642;</mtext></math>=<span>1D642</span></span>
+ <span><math class="testfont"><mtext>&#x1D643;</mtext></math>=<span>1D643</span></span>
+ <span><math class="testfont"><mtext>&#x1D644;</mtext></math>=<span>1D644</span></span>
+ <span><math class="testfont"><mtext>&#x1D645;</mtext></math>=<span>1D645</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D646;</mtext></math>=<span>1D646</span></span>
+ <span><math class="testfont"><mtext>&#x1D647;</mtext></math>=<span>1D647</span></span>
+ <span><math class="testfont"><mtext>&#x1D648;</mtext></math>=<span>1D648</span></span>
+ <span><math class="testfont"><mtext>&#x1D649;</mtext></math>=<span>1D649</span></span>
+ <span><math class="testfont"><mtext>&#x1D64A;</mtext></math>=<span>1D64A</span></span>
+ <span><math class="testfont"><mtext>&#x1D64B;</mtext></math>=<span>1D64B</span></span>
+ <span><math class="testfont"><mtext>&#x1D64C;</mtext></math>=<span>1D64C</span></span>
+ <span><math class="testfont"><mtext>&#x1D64D;</mtext></math>=<span>1D64D</span></span>
+ <span><math class="testfont"><mtext>&#x1D64E;</mtext></math>=<span>1D64E</span></span>
+ <span><math class="testfont"><mtext>&#x1D64F;</mtext></math>=<span>1D64F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D650;</mtext></math>=<span>1D650</span></span>
+ <span><math class="testfont"><mtext>&#x1D651;</mtext></math>=<span>1D651</span></span>
+ <span><math class="testfont"><mtext>&#x1D652;</mtext></math>=<span>1D652</span></span>
+ <span><math class="testfont"><mtext>&#x1D653;</mtext></math>=<span>1D653</span></span>
+ <span><math class="testfont"><mtext>&#x1D654;</mtext></math>=<span>1D654</span></span>
+ <span><math class="testfont"><mtext>&#x1D655;</mtext></math>=<span>1D655</span></span>
+ <span><math class="testfont"><mtext>&#x1D656;</mtext></math>=<span>1D656</span></span>
+ <span><math class="testfont"><mtext>&#x1D657;</mtext></math>=<span>1D657</span></span>
+ <span><math class="testfont"><mtext>&#x1D658;</mtext></math>=<span>1D658</span></span>
+ <span><math class="testfont"><mtext>&#x1D659;</mtext></math>=<span>1D659</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D65A;</mtext></math>=<span>1D65A</span></span>
+ <span><math class="testfont"><mtext>&#x1D65B;</mtext></math>=<span>1D65B</span></span>
+ <span><math class="testfont"><mtext>&#x1D65C;</mtext></math>=<span>1D65C</span></span>
+ <span><math class="testfont"><mtext>&#x1D65D;</mtext></math>=<span>1D65D</span></span>
+ <span><math class="testfont"><mtext>&#x1D65E;</mtext></math>=<span>1D65E</span></span>
+ <span><math class="testfont"><mtext>&#x1D65F;</mtext></math>=<span>1D65F</span></span>
+ <span><math class="testfont"><mtext>&#x1D660;</mtext></math>=<span>1D660</span></span>
+ <span><math class="testfont"><mtext>&#x1D661;</mtext></math>=<span>1D661</span></span>
+ <span><math class="testfont"><mtext>&#x1D662;</mtext></math>=<span>1D662</span></span>
+ <span><math class="testfont"><mtext>&#x1D663;</mtext></math>=<span>1D663</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D664;</mtext></math>=<span>1D664</span></span>
+ <span><math class="testfont"><mtext>&#x1D665;</mtext></math>=<span>1D665</span></span>
+ <span><math class="testfont"><mtext>&#x1D666;</mtext></math>=<span>1D666</span></span>
+ <span><math class="testfont"><mtext>&#x1D667;</mtext></math>=<span>1D667</span></span>
+ <span><math class="testfont"><mtext>&#x1D668;</mtext></math>=<span>1D668</span></span>
+ <span><math class="testfont"><mtext>&#x1D669;</mtext></math>=<span>1D669</span></span>
+ <span><math class="testfont"><mtext>&#x1D66A;</mtext></math>=<span>1D66A</span></span>
+ <span><math class="testfont"><mtext>&#x1D66B;</mtext></math>=<span>1D66B</span></span>
+ <span><math class="testfont"><mtext>&#x1D66C;</mtext></math>=<span>1D66C</span></span>
+ <span><math class="testfont"><mtext>&#x1D66D;</mtext></math>=<span>1D66D</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D66E;</mtext></math>=<span>1D66E</span></span>
+ <span><math class="testfont"><mtext>&#x1D66F;</mtext></math>=<span>1D66F</span></span>
+ <span><math class="testfont"><mtext>&#x1D790;</mtext></math>=<span>1D790</span></span>
+ <span><math class="testfont"><mtext>&#x1D791;</mtext></math>=<span>1D791</span></span>
+ <span><math class="testfont"><mtext>&#x1D792;</mtext></math>=<span>1D792</span></span>
+ <span><math class="testfont"><mtext>&#x1D793;</mtext></math>=<span>1D793</span></span>
+ <span><math class="testfont"><mtext>&#x1D794;</mtext></math>=<span>1D794</span></span>
+ <span><math class="testfont"><mtext>&#x1D795;</mtext></math>=<span>1D795</span></span>
+ <span><math class="testfont"><mtext>&#x1D796;</mtext></math>=<span>1D796</span></span>
+ <span><math class="testfont"><mtext>&#x1D797;</mtext></math>=<span>1D797</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D798;</mtext></math>=<span>1D798</span></span>
+ <span><math class="testfont"><mtext>&#x1D799;</mtext></math>=<span>1D799</span></span>
+ <span><math class="testfont"><mtext>&#x1D79A;</mtext></math>=<span>1D79A</span></span>
+ <span><math class="testfont"><mtext>&#x1D79B;</mtext></math>=<span>1D79B</span></span>
+ <span><math class="testfont"><mtext>&#x1D79C;</mtext></math>=<span>1D79C</span></span>
+ <span><math class="testfont"><mtext>&#x1D79D;</mtext></math>=<span>1D79D</span></span>
+ <span><math class="testfont"><mtext>&#x1D79E;</mtext></math>=<span>1D79E</span></span>
+ <span><math class="testfont"><mtext>&#x1D79F;</mtext></math>=<span>1D79F</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A0;</mtext></math>=<span>1D7A0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A1;</mtext></math>=<span>1D7A1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7A2;</mtext></math>=<span>1D7A2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A3;</mtext></math>=<span>1D7A3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A4;</mtext></math>=<span>1D7A4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A5;</mtext></math>=<span>1D7A5</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A6;</mtext></math>=<span>1D7A6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A7;</mtext></math>=<span>1D7A7</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A8;</mtext></math>=<span>1D7A8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7A9;</mtext></math>=<span>1D7A9</span></span>
+ <span><math class="testfont"><mtext>&#x1D7AA;</mtext></math>=<span>1D7AA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7AB;</mtext></math>=<span>1D7AB</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7AC;</mtext></math>=<span>1D7AC</span></span>
+ <span><math class="testfont"><mtext>&#x1D7AD;</mtext></math>=<span>1D7AD</span></span>
+ <span><math class="testfont"><mtext>&#x1D7AE;</mtext></math>=<span>1D7AE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7AF;</mtext></math>=<span>1D7AF</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B0;</mtext></math>=<span>1D7B0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B1;</mtext></math>=<span>1D7B1</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B2;</mtext></math>=<span>1D7B2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B3;</mtext></math>=<span>1D7B3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B4;</mtext></math>=<span>1D7B4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B5;</mtext></math>=<span>1D7B5</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7B6;</mtext></math>=<span>1D7B6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B7;</mtext></math>=<span>1D7B7</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B8;</mtext></math>=<span>1D7B8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7B9;</mtext></math>=<span>1D7B9</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BA;</mtext></math>=<span>1D7BA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BB;</mtext></math>=<span>1D7BB</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BC;</mtext></math>=<span>1D7BC</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BD;</mtext></math>=<span>1D7BD</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BE;</mtext></math>=<span>1D7BE</span></span>
+ <span><math class="testfont"><mtext>&#x1D7BF;</mtext></math>=<span>1D7BF</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7C0;</mtext></math>=<span>1D7C0</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C1;</mtext></math>=<span>1D7C1</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C2;</mtext></math>=<span>1D7C2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C3;</mtext></math>=<span>1D7C3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C4;</mtext></math>=<span>1D7C4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C5;</mtext></math>=<span>1D7C5</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C6;</mtext></math>=<span>1D7C6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C7;</mtext></math>=<span>1D7C7</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C8;</mtext></math>=<span>1D7C8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7C9;</mtext></math>=<span>1D7C9</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic.html
new file mode 100644
index 0000000000..d51afe4345
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-bold-italic.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif-bold-italic</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#sans-serif-bold-italic-mappings">
+<link rel="match" href="mathvariant-sans-serif-bold-italic-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif-bold-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x41;</mtext></math>=<span>1D63C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x42;</mtext></math>=<span>1D63D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x43;</mtext></math>=<span>1D63E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x44;</mtext></math>=<span>1D63F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x45;</mtext></math>=<span>1D640</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x46;</mtext></math>=<span>1D641</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x47;</mtext></math>=<span>1D642</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x48;</mtext></math>=<span>1D643</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x49;</mtext></math>=<span>1D644</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4A;</mtext></math>=<span>1D645</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4B;</mtext></math>=<span>1D646</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4C;</mtext></math>=<span>1D647</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4D;</mtext></math>=<span>1D648</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4E;</mtext></math>=<span>1D649</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x4F;</mtext></math>=<span>1D64A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x50;</mtext></math>=<span>1D64B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x51;</mtext></math>=<span>1D64C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x52;</mtext></math>=<span>1D64D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x53;</mtext></math>=<span>1D64E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x54;</mtext></math>=<span>1D64F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x55;</mtext></math>=<span>1D650</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x56;</mtext></math>=<span>1D651</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x57;</mtext></math>=<span>1D652</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x58;</mtext></math>=<span>1D653</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x59;</mtext></math>=<span>1D654</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x5A;</mtext></math>=<span>1D655</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x61;</mtext></math>=<span>1D656</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x62;</mtext></math>=<span>1D657</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x63;</mtext></math>=<span>1D658</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x64;</mtext></math>=<span>1D659</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x65;</mtext></math>=<span>1D65A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x66;</mtext></math>=<span>1D65B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x67;</mtext></math>=<span>1D65C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x68;</mtext></math>=<span>1D65D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x69;</mtext></math>=<span>1D65E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6A;</mtext></math>=<span>1D65F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6B;</mtext></math>=<span>1D660</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6C;</mtext></math>=<span>1D661</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6D;</mtext></math>=<span>1D662</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6E;</mtext></math>=<span>1D663</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x6F;</mtext></math>=<span>1D664</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x70;</mtext></math>=<span>1D665</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x71;</mtext></math>=<span>1D666</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x72;</mtext></math>=<span>1D667</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x73;</mtext></math>=<span>1D668</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x74;</mtext></math>=<span>1D669</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x75;</mtext></math>=<span>1D66A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x76;</mtext></math>=<span>1D66B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x77;</mtext></math>=<span>1D66C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x78;</mtext></math>=<span>1D66D</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x79;</mtext></math>=<span>1D66E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x7A;</mtext></math>=<span>1D66F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x391;</mtext></math>=<span>1D790</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x392;</mtext></math>=<span>1D791</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x393;</mtext></math>=<span>1D792</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x394;</mtext></math>=<span>1D793</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x395;</mtext></math>=<span>1D794</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x396;</mtext></math>=<span>1D795</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x397;</mtext></math>=<span>1D796</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x398;</mtext></math>=<span>1D797</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x399;</mtext></math>=<span>1D798</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39A;</mtext></math>=<span>1D799</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39B;</mtext></math>=<span>1D79A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39C;</mtext></math>=<span>1D79B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39D;</mtext></math>=<span>1D79C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39E;</mtext></math>=<span>1D79D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x39F;</mtext></math>=<span>1D79E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A0;</mtext></math>=<span>1D79F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A1;</mtext></math>=<span>1D7A0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3F4;</mtext></math>=<span>1D7A1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A3;</mtext></math>=<span>1D7A2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A4;</mtext></math>=<span>1D7A3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A5;</mtext></math>=<span>1D7A4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A6;</mtext></math>=<span>1D7A5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A7;</mtext></math>=<span>1D7A6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A8;</mtext></math>=<span>1D7A7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3A9;</mtext></math>=<span>1D7A8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x2207;</mtext></math>=<span>1D7A9</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B1;</mtext></math>=<span>1D7AA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B2;</mtext></math>=<span>1D7AB</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B3;</mtext></math>=<span>1D7AC</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B4;</mtext></math>=<span>1D7AD</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B5;</mtext></math>=<span>1D7AE</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B6;</mtext></math>=<span>1D7AF</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B7;</mtext></math>=<span>1D7B0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B8;</mtext></math>=<span>1D7B1</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3B9;</mtext></math>=<span>1D7B2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BA;</mtext></math>=<span>1D7B3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BB;</mtext></math>=<span>1D7B4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BC;</mtext></math>=<span>1D7B5</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BD;</mtext></math>=<span>1D7B6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BE;</mtext></math>=<span>1D7B7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3BF;</mtext></math>=<span>1D7B8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C0;</mtext></math>=<span>1D7B9</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C1;</mtext></math>=<span>1D7BA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C2;</mtext></math>=<span>1D7BB</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C3;</mtext></math>=<span>1D7BC</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C4;</mtext></math>=<span>1D7BD</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C5;</mtext></math>=<span>1D7BE</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C6;</mtext></math>=<span>1D7BF</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C7;</mtext></math>=<span>1D7C0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C8;</mtext></math>=<span>1D7C1</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3C9;</mtext></math>=<span>1D7C2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x2202;</mtext></math>=<span>1D7C3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3F5;</mtext></math>=<span>1D7C4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3D1;</mtext></math>=<span>1D7C5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3F0;</mtext></math>=<span>1D7C6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3D5;</mtext></math>=<span>1D7C7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3F1;</mtext></math>=<span>1D7C8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-bold-italic">&#x3D6;</mtext></math>=<span>1D7C9</span></span><br/>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic-ref.html
new file mode 100644
index 0000000000..d7e23248c6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif-italic (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D608;</mtext></math>=<span>1D608</span></span>
+ <span><math class="testfont"><mtext>&#x1D609;</mtext></math>=<span>1D609</span></span>
+ <span><math class="testfont"><mtext>&#x1D60A;</mtext></math>=<span>1D60A</span></span>
+ <span><math class="testfont"><mtext>&#x1D60B;</mtext></math>=<span>1D60B</span></span>
+ <span><math class="testfont"><mtext>&#x1D60C;</mtext></math>=<span>1D60C</span></span>
+ <span><math class="testfont"><mtext>&#x1D60D;</mtext></math>=<span>1D60D</span></span>
+ <span><math class="testfont"><mtext>&#x1D60E;</mtext></math>=<span>1D60E</span></span>
+ <span><math class="testfont"><mtext>&#x1D60F;</mtext></math>=<span>1D60F</span></span>
+ <span><math class="testfont"><mtext>&#x1D610;</mtext></math>=<span>1D610</span></span>
+ <span><math class="testfont"><mtext>&#x1D611;</mtext></math>=<span>1D611</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D612;</mtext></math>=<span>1D612</span></span>
+ <span><math class="testfont"><mtext>&#x1D613;</mtext></math>=<span>1D613</span></span>
+ <span><math class="testfont"><mtext>&#x1D614;</mtext></math>=<span>1D614</span></span>
+ <span><math class="testfont"><mtext>&#x1D615;</mtext></math>=<span>1D615</span></span>
+ <span><math class="testfont"><mtext>&#x1D616;</mtext></math>=<span>1D616</span></span>
+ <span><math class="testfont"><mtext>&#x1D617;</mtext></math>=<span>1D617</span></span>
+ <span><math class="testfont"><mtext>&#x1D618;</mtext></math>=<span>1D618</span></span>
+ <span><math class="testfont"><mtext>&#x1D619;</mtext></math>=<span>1D619</span></span>
+ <span><math class="testfont"><mtext>&#x1D61A;</mtext></math>=<span>1D61A</span></span>
+ <span><math class="testfont"><mtext>&#x1D61B;</mtext></math>=<span>1D61B</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D61C;</mtext></math>=<span>1D61C</span></span>
+ <span><math class="testfont"><mtext>&#x1D61D;</mtext></math>=<span>1D61D</span></span>
+ <span><math class="testfont"><mtext>&#x1D61E;</mtext></math>=<span>1D61E</span></span>
+ <span><math class="testfont"><mtext>&#x1D61F;</mtext></math>=<span>1D61F</span></span>
+ <span><math class="testfont"><mtext>&#x1D620;</mtext></math>=<span>1D620</span></span>
+ <span><math class="testfont"><mtext>&#x1D621;</mtext></math>=<span>1D621</span></span>
+ <span><math class="testfont"><mtext>&#x1D622;</mtext></math>=<span>1D622</span></span>
+ <span><math class="testfont"><mtext>&#x1D623;</mtext></math>=<span>1D623</span></span>
+ <span><math class="testfont"><mtext>&#x1D624;</mtext></math>=<span>1D624</span></span>
+ <span><math class="testfont"><mtext>&#x1D625;</mtext></math>=<span>1D625</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D626;</mtext></math>=<span>1D626</span></span>
+ <span><math class="testfont"><mtext>&#x1D627;</mtext></math>=<span>1D627</span></span>
+ <span><math class="testfont"><mtext>&#x1D628;</mtext></math>=<span>1D628</span></span>
+ <span><math class="testfont"><mtext>&#x1D629;</mtext></math>=<span>1D629</span></span>
+ <span><math class="testfont"><mtext>&#x1D62A;</mtext></math>=<span>1D62A</span></span>
+ <span><math class="testfont"><mtext>&#x1D62B;</mtext></math>=<span>1D62B</span></span>
+ <span><math class="testfont"><mtext>&#x1D62C;</mtext></math>=<span>1D62C</span></span>
+ <span><math class="testfont"><mtext>&#x1D62D;</mtext></math>=<span>1D62D</span></span>
+ <span><math class="testfont"><mtext>&#x1D62E;</mtext></math>=<span>1D62E</span></span>
+ <span><math class="testfont"><mtext>&#x1D62F;</mtext></math>=<span>1D62F</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D630;</mtext></math>=<span>1D630</span></span>
+ <span><math class="testfont"><mtext>&#x1D631;</mtext></math>=<span>1D631</span></span>
+ <span><math class="testfont"><mtext>&#x1D632;</mtext></math>=<span>1D632</span></span>
+ <span><math class="testfont"><mtext>&#x1D633;</mtext></math>=<span>1D633</span></span>
+ <span><math class="testfont"><mtext>&#x1D634;</mtext></math>=<span>1D634</span></span>
+ <span><math class="testfont"><mtext>&#x1D635;</mtext></math>=<span>1D635</span></span>
+ <span><math class="testfont"><mtext>&#x1D636;</mtext></math>=<span>1D636</span></span>
+ <span><math class="testfont"><mtext>&#x1D637;</mtext></math>=<span>1D637</span></span>
+ <span><math class="testfont"><mtext>&#x1D638;</mtext></math>=<span>1D638</span></span>
+ <span><math class="testfont"><mtext>&#x1D639;</mtext></math>=<span>1D639</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D63A;</mtext></math>=<span>1D63A</span></span>
+ <span><math class="testfont"><mtext>&#x1D63B;</mtext></math>=<span>1D63B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic.html
new file mode 100644
index 0000000000..e847ca9bb8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-italic.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif-italic</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#sans-serif-italic-mappings">
+<link rel="match" href="mathvariant-sans-serif-italic-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x41;</mtext></math>=<span>1D608</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x42;</mtext></math>=<span>1D609</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x43;</mtext></math>=<span>1D60A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x44;</mtext></math>=<span>1D60B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x45;</mtext></math>=<span>1D60C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x46;</mtext></math>=<span>1D60D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x47;</mtext></math>=<span>1D60E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x48;</mtext></math>=<span>1D60F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x49;</mtext></math>=<span>1D610</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4A;</mtext></math>=<span>1D611</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4B;</mtext></math>=<span>1D612</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4C;</mtext></math>=<span>1D613</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4D;</mtext></math>=<span>1D614</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4E;</mtext></math>=<span>1D615</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x4F;</mtext></math>=<span>1D616</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x50;</mtext></math>=<span>1D617</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x51;</mtext></math>=<span>1D618</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x52;</mtext></math>=<span>1D619</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x53;</mtext></math>=<span>1D61A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x54;</mtext></math>=<span>1D61B</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x55;</mtext></math>=<span>1D61C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x56;</mtext></math>=<span>1D61D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x57;</mtext></math>=<span>1D61E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x58;</mtext></math>=<span>1D61F</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x59;</mtext></math>=<span>1D620</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x5A;</mtext></math>=<span>1D621</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x61;</mtext></math>=<span>1D622</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x62;</mtext></math>=<span>1D623</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x63;</mtext></math>=<span>1D624</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x64;</mtext></math>=<span>1D625</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x65;</mtext></math>=<span>1D626</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x66;</mtext></math>=<span>1D627</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x67;</mtext></math>=<span>1D628</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x68;</mtext></math>=<span>1D629</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x69;</mtext></math>=<span>1D62A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6A;</mtext></math>=<span>1D62B</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6B;</mtext></math>=<span>1D62C</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6C;</mtext></math>=<span>1D62D</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6D;</mtext></math>=<span>1D62E</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6E;</mtext></math>=<span>1D62F</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x6F;</mtext></math>=<span>1D630</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x70;</mtext></math>=<span>1D631</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x71;</mtext></math>=<span>1D632</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x72;</mtext></math>=<span>1D633</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x73;</mtext></math>=<span>1D634</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x74;</mtext></math>=<span>1D635</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x75;</mtext></math>=<span>1D636</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x76;</mtext></math>=<span>1D637</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x77;</mtext></math>=<span>1D638</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x78;</mtext></math>=<span>1D639</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x79;</mtext></math>=<span>1D63A</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif-italic">&#x7A;</mtext></math>=<span>1D63B</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-ref.html
new file mode 100644
index 0000000000..ced5272ecb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif-ref.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D5A0;</mtext></math>=<span>1D5A0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A1;</mtext></math>=<span>1D5A1</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A2;</mtext></math>=<span>1D5A2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A3;</mtext></math>=<span>1D5A3</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A4;</mtext></math>=<span>1D5A4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A5;</mtext></math>=<span>1D5A5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A6;</mtext></math>=<span>1D5A6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A7;</mtext></math>=<span>1D5A7</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A8;</mtext></math>=<span>1D5A8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5A9;</mtext></math>=<span>1D5A9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5AA;</mtext></math>=<span>1D5AA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5AB;</mtext></math>=<span>1D5AB</span></span>
+ <span><math class="testfont"><mtext>&#x1D5AC;</mtext></math>=<span>1D5AC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5AD;</mtext></math>=<span>1D5AD</span></span>
+ <span><math class="testfont"><mtext>&#x1D5AE;</mtext></math>=<span>1D5AE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5AF;</mtext></math>=<span>1D5AF</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B0;</mtext></math>=<span>1D5B0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B1;</mtext></math>=<span>1D5B1</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B2;</mtext></math>=<span>1D5B2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B3;</mtext></math>=<span>1D5B3</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5B4;</mtext></math>=<span>1D5B4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B5;</mtext></math>=<span>1D5B5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B6;</mtext></math>=<span>1D5B6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B7;</mtext></math>=<span>1D5B7</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B8;</mtext></math>=<span>1D5B8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5B9;</mtext></math>=<span>1D5B9</span></span>
+ <span><math class="testfont"><mtext>&#x1D5BA;</mtext></math>=<span>1D5BA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5BB;</mtext></math>=<span>1D5BB</span></span>
+ <span><math class="testfont"><mtext>&#x1D5BC;</mtext></math>=<span>1D5BC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5BD;</mtext></math>=<span>1D5BD</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5BE;</mtext></math>=<span>1D5BE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5BF;</mtext></math>=<span>1D5BF</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C0;</mtext></math>=<span>1D5C0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C1;</mtext></math>=<span>1D5C1</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C2;</mtext></math>=<span>1D5C2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C3;</mtext></math>=<span>1D5C3</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C4;</mtext></math>=<span>1D5C4</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C5;</mtext></math>=<span>1D5C5</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C6;</mtext></math>=<span>1D5C6</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C7;</mtext></math>=<span>1D5C7</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5C8;</mtext></math>=<span>1D5C8</span></span>
+ <span><math class="testfont"><mtext>&#x1D5C9;</mtext></math>=<span>1D5C9</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CA;</mtext></math>=<span>1D5CA</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CB;</mtext></math>=<span>1D5CB</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CC;</mtext></math>=<span>1D5CC</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CD;</mtext></math>=<span>1D5CD</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CE;</mtext></math>=<span>1D5CE</span></span>
+ <span><math class="testfont"><mtext>&#x1D5CF;</mtext></math>=<span>1D5CF</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D0;</mtext></math>=<span>1D5D0</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D1;</mtext></math>=<span>1D5D1</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D5D2;</mtext></math>=<span>1D5D2</span></span>
+ <span><math class="testfont"><mtext>&#x1D5D3;</mtext></math>=<span>1D5D3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E2;</mtext></math>=<span>1D7E2</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E3;</mtext></math>=<span>1D7E3</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E4;</mtext></math>=<span>1D7E4</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E5;</mtext></math>=<span>1D7E5</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E6;</mtext></math>=<span>1D7E6</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E7;</mtext></math>=<span>1D7E7</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E8;</mtext></math>=<span>1D7E8</span></span>
+ <span><math class="testfont"><mtext>&#x1D7E9;</mtext></math>=<span>1D7E9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D7EA;</mtext></math>=<span>1D7EA</span></span>
+ <span><math class="testfont"><mtext>&#x1D7EB;</mtext></math>=<span>1D7EB</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif.html
new file mode 100644
index 0000000000..43a1fa821f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-sans-serif.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant sans-serif</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#sans-serif-mappings">
+<link rel="match" href="mathvariant-sans-serif-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x41;</mtext></math>=<span>1D5A0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x42;</mtext></math>=<span>1D5A1</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x43;</mtext></math>=<span>1D5A2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x44;</mtext></math>=<span>1D5A3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x45;</mtext></math>=<span>1D5A4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x46;</mtext></math>=<span>1D5A5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x47;</mtext></math>=<span>1D5A6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x48;</mtext></math>=<span>1D5A7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x49;</mtext></math>=<span>1D5A8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4A;</mtext></math>=<span>1D5A9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4B;</mtext></math>=<span>1D5AA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4C;</mtext></math>=<span>1D5AB</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4D;</mtext></math>=<span>1D5AC</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4E;</mtext></math>=<span>1D5AD</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x4F;</mtext></math>=<span>1D5AE</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x50;</mtext></math>=<span>1D5AF</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x51;</mtext></math>=<span>1D5B0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x52;</mtext></math>=<span>1D5B1</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x53;</mtext></math>=<span>1D5B2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x54;</mtext></math>=<span>1D5B3</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x55;</mtext></math>=<span>1D5B4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x56;</mtext></math>=<span>1D5B5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x57;</mtext></math>=<span>1D5B6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x58;</mtext></math>=<span>1D5B7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x59;</mtext></math>=<span>1D5B8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x5A;</mtext></math>=<span>1D5B9</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x61;</mtext></math>=<span>1D5BA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x62;</mtext></math>=<span>1D5BB</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x63;</mtext></math>=<span>1D5BC</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x64;</mtext></math>=<span>1D5BD</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x65;</mtext></math>=<span>1D5BE</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x66;</mtext></math>=<span>1D5BF</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x67;</mtext></math>=<span>1D5C0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x68;</mtext></math>=<span>1D5C1</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x69;</mtext></math>=<span>1D5C2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6A;</mtext></math>=<span>1D5C3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6B;</mtext></math>=<span>1D5C4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6C;</mtext></math>=<span>1D5C5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6D;</mtext></math>=<span>1D5C6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6E;</mtext></math>=<span>1D5C7</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x6F;</mtext></math>=<span>1D5C8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x70;</mtext></math>=<span>1D5C9</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x71;</mtext></math>=<span>1D5CA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x72;</mtext></math>=<span>1D5CB</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x73;</mtext></math>=<span>1D5CC</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x74;</mtext></math>=<span>1D5CD</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x75;</mtext></math>=<span>1D5CE</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x76;</mtext></math>=<span>1D5CF</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x77;</mtext></math>=<span>1D5D0</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x78;</mtext></math>=<span>1D5D1</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x79;</mtext></math>=<span>1D5D2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x7A;</mtext></math>=<span>1D5D3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x30;</mtext></math>=<span>1D7E2</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x31;</mtext></math>=<span>1D7E3</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x32;</mtext></math>=<span>1D7E4</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x33;</mtext></math>=<span>1D7E5</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x34;</mtext></math>=<span>1D7E6</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x35;</mtext></math>=<span>1D7E7</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x36;</mtext></math>=<span>1D7E8</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x37;</mtext></math>=<span>1D7E9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x38;</mtext></math>=<span>1D7EA</span></span>
+ <span><math class="testfont"><mtext mathvariant="sans-serif">&#x39;</mtext></math>=<span>1D7EB</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script-ref.html
new file mode 100644
index 0000000000..60ced85bc3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant script (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1D49C;</mtext></math>=<span>1D49C</span></span>
+ <span><math class="testfont"><mtext>&#x212C;</mtext></math>=<span>0212C</span></span>
+ <span><math class="testfont"><mtext>&#x1D49E;</mtext></math>=<span>1D49E</span></span>
+ <span><math class="testfont"><mtext>&#x1D49F;</mtext></math>=<span>1D49F</span></span>
+ <span><math class="testfont"><mtext>&#x2130;</mtext></math>=<span>02130</span></span>
+ <span><math class="testfont"><mtext>&#x2131;</mtext></math>=<span>02131</span></span>
+ <span><math class="testfont"><mtext>&#x1D4A2;</mtext></math>=<span>1D4A2</span></span>
+ <span><math class="testfont"><mtext>&#x210B;</mtext></math>=<span>0210B</span></span>
+ <span><math class="testfont"><mtext>&#x2110;</mtext></math>=<span>02110</span></span>
+ <span><math class="testfont"><mtext>&#x1D4A5;</mtext></math>=<span>1D4A5</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4A6;</mtext></math>=<span>1D4A6</span></span>
+ <span><math class="testfont"><mtext>&#x2112;</mtext></math>=<span>02112</span></span>
+ <span><math class="testfont"><mtext>&#x2133;</mtext></math>=<span>02133</span></span>
+ <span><math class="testfont"><mtext>&#x1D4A9;</mtext></math>=<span>1D4A9</span></span>
+ <span><math class="testfont"><mtext>&#x1D4AA;</mtext></math>=<span>1D4AA</span></span>
+ <span><math class="testfont"><mtext>&#x1D4AB;</mtext></math>=<span>1D4AB</span></span>
+ <span><math class="testfont"><mtext>&#x1D4AC;</mtext></math>=<span>1D4AC</span></span>
+ <span><math class="testfont"><mtext>&#x211B;</mtext></math>=<span>0211B</span></span>
+ <span><math class="testfont"><mtext>&#x1D4AE;</mtext></math>=<span>1D4AE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4AF;</mtext></math>=<span>1D4AF</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4B0;</mtext></math>=<span>1D4B0</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B1;</mtext></math>=<span>1D4B1</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B2;</mtext></math>=<span>1D4B2</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B3;</mtext></math>=<span>1D4B3</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B4;</mtext></math>=<span>1D4B4</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B5;</mtext></math>=<span>1D4B5</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B6;</mtext></math>=<span>1D4B6</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B7;</mtext></math>=<span>1D4B7</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B8;</mtext></math>=<span>1D4B8</span></span>
+ <span><math class="testfont"><mtext>&#x1D4B9;</mtext></math>=<span>1D4B9</span></span><br/>
+ <span><math class="testfont"><mtext>&#x212F;</mtext></math>=<span>0212F</span></span>
+ <span><math class="testfont"><mtext>&#x1D4BB;</mtext></math>=<span>1D4BB</span></span>
+ <span><math class="testfont"><mtext>&#x210A;</mtext></math>=<span>0210A</span></span>
+ <span><math class="testfont"><mtext>&#x1D4BD;</mtext></math>=<span>1D4BD</span></span>
+ <span><math class="testfont"><mtext>&#x1D4BE;</mtext></math>=<span>1D4BE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4BF;</mtext></math>=<span>1D4BF</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C0;</mtext></math>=<span>1D4C0</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C1;</mtext></math>=<span>1D4C1</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C2;</mtext></math>=<span>1D4C2</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C3;</mtext></math>=<span>1D4C3</span></span><br/>
+ <span><math class="testfont"><mtext>&#x2134;</mtext></math>=<span>02134</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C5;</mtext></math>=<span>1D4C5</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C6;</mtext></math>=<span>1D4C6</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C7;</mtext></math>=<span>1D4C7</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C8;</mtext></math>=<span>1D4C8</span></span>
+ <span><math class="testfont"><mtext>&#x1D4C9;</mtext></math>=<span>1D4C9</span></span>
+ <span><math class="testfont"><mtext>&#x1D4CA;</mtext></math>=<span>1D4CA</span></span>
+ <span><math class="testfont"><mtext>&#x1D4CB;</mtext></math>=<span>1D4CB</span></span>
+ <span><math class="testfont"><mtext>&#x1D4CC;</mtext></math>=<span>1D4CC</span></span>
+ <span><math class="testfont"><mtext>&#x1D4CD;</mtext></math>=<span>1D4CD</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1D4CE;</mtext></math>=<span>1D4CE</span></span>
+ <span><math class="testfont"><mtext>&#x1D4CF;</mtext></math>=<span>1D4CF</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script.html
new file mode 100644
index 0000000000..afbdfd9f94
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-script.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant script</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#script-mappings">
+<link rel="match" href="mathvariant-script-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a script mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="script">&#x41;</mtext></math>=<span>1D49C</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x42;</mtext></math>=<span>0212C</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x43;</mtext></math>=<span>1D49E</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x44;</mtext></math>=<span>1D49F</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x45;</mtext></math>=<span>02130</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x46;</mtext></math>=<span>02131</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x47;</mtext></math>=<span>1D4A2</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x48;</mtext></math>=<span>0210B</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x49;</mtext></math>=<span>02110</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4A;</mtext></math>=<span>1D4A5</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4B;</mtext></math>=<span>1D4A6</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4C;</mtext></math>=<span>02112</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4D;</mtext></math>=<span>02133</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4E;</mtext></math>=<span>1D4A9</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x4F;</mtext></math>=<span>1D4AA</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x50;</mtext></math>=<span>1D4AB</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x51;</mtext></math>=<span>1D4AC</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x52;</mtext></math>=<span>0211B</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x53;</mtext></math>=<span>1D4AE</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x54;</mtext></math>=<span>1D4AF</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="script">&#x55;</mtext></math>=<span>1D4B0</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x56;</mtext></math>=<span>1D4B1</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x57;</mtext></math>=<span>1D4B2</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x58;</mtext></math>=<span>1D4B3</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x59;</mtext></math>=<span>1D4B4</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x5A;</mtext></math>=<span>1D4B5</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x61;</mtext></math>=<span>1D4B6</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x62;</mtext></math>=<span>1D4B7</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x63;</mtext></math>=<span>1D4B8</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x64;</mtext></math>=<span>1D4B9</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="script">&#x65;</mtext></math>=<span>0212F</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x66;</mtext></math>=<span>1D4BB</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x67;</mtext></math>=<span>0210A</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x68;</mtext></math>=<span>1D4BD</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x69;</mtext></math>=<span>1D4BE</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6A;</mtext></math>=<span>1D4BF</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6B;</mtext></math>=<span>1D4C0</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6C;</mtext></math>=<span>1D4C1</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6D;</mtext></math>=<span>1D4C2</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6E;</mtext></math>=<span>1D4C3</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="script">&#x6F;</mtext></math>=<span>02134</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x70;</mtext></math>=<span>1D4C5</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x71;</mtext></math>=<span>1D4C6</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x72;</mtext></math>=<span>1D4C7</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x73;</mtext></math>=<span>1D4C8</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x74;</mtext></math>=<span>1D4C9</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x75;</mtext></math>=<span>1D4CA</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x76;</mtext></math>=<span>1D4CB</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x77;</mtext></math>=<span>1D4CC</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x78;</mtext></math>=<span>1D4CD</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="script">&#x79;</mtext></math>=<span>1D4CE</span></span>
+ <span><math class="testfont"><mtext mathvariant="script">&#x7A;</mtext></math>=<span>1D4CF</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched-ref.html
new file mode 100644
index 0000000000..454f2004ac
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched-ref.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant stretched (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1EE61;</mtext></math>=<span>1EE61</span></span>
+ <span><math class="testfont"><mtext>&#x1EE62;</mtext></math>=<span>1EE62</span></span>
+ <span><math class="testfont"><mtext>&#x1EE64;</mtext></math>=<span>1EE64</span></span>
+ <span><math class="testfont"><mtext>&#x1EE67;</mtext></math>=<span>1EE67</span></span>
+ <span><math class="testfont"><mtext>&#x1EE68;</mtext></math>=<span>1EE68</span></span>
+ <span><math class="testfont"><mtext>&#x1EE69;</mtext></math>=<span>1EE69</span></span>
+ <span><math class="testfont"><mtext>&#x1EE6A;</mtext></math>=<span>1EE6A</span></span>
+ <span><math class="testfont"><mtext>&#x1EE6C;</mtext></math>=<span>1EE6C</span></span>
+ <span><math class="testfont"><mtext>&#x1EE6D;</mtext></math>=<span>1EE6D</span></span>
+ <span><math class="testfont"><mtext>&#x1EE6E;</mtext></math>=<span>1EE6E</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE6F;</mtext></math>=<span>1EE6F</span></span>
+ <span><math class="testfont"><mtext>&#x1EE70;</mtext></math>=<span>1EE70</span></span>
+ <span><math class="testfont"><mtext>&#x1EE71;</mtext></math>=<span>1EE71</span></span>
+ <span><math class="testfont"><mtext>&#x1EE72;</mtext></math>=<span>1EE72</span></span>
+ <span><math class="testfont"><mtext>&#x1EE74;</mtext></math>=<span>1EE74</span></span>
+ <span><math class="testfont"><mtext>&#x1EE75;</mtext></math>=<span>1EE75</span></span>
+ <span><math class="testfont"><mtext>&#x1EE76;</mtext></math>=<span>1EE76</span></span>
+ <span><math class="testfont"><mtext>&#x1EE77;</mtext></math>=<span>1EE77</span></span>
+ <span><math class="testfont"><mtext>&#x1EE79;</mtext></math>=<span>1EE79</span></span>
+ <span><math class="testfont"><mtext>&#x1EE7A;</mtext></math>=<span>1EE7A</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE7B;</mtext></math>=<span>1EE7B</span></span>
+ <span><math class="testfont"><mtext>&#x1EE7C;</mtext></math>=<span>1EE7C</span></span>
+ <span><math class="testfont"><mtext>&#x1EE7E;</mtext></math>=<span>1EE7E</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched.html
new file mode 100644
index 0000000000..99b06fb41b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-stretched.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant stretched</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#stretched-mappings">
+<link rel="match" href="mathvariant-stretched-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a stretched mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x628;</mtext></math>=<span>1EE61</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x62C;</mtext></math>=<span>1EE62</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x647;</mtext></math>=<span>1EE64</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x62D;</mtext></math>=<span>1EE67</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x637;</mtext></math>=<span>1EE68</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x64A;</mtext></math>=<span>1EE69</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x643;</mtext></math>=<span>1EE6A</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x645;</mtext></math>=<span>1EE6C</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x646;</mtext></math>=<span>1EE6D</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x633;</mtext></math>=<span>1EE6E</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x639;</mtext></math>=<span>1EE6F</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x641;</mtext></math>=<span>1EE70</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x635;</mtext></math>=<span>1EE71</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x642;</mtext></math>=<span>1EE72</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x634;</mtext></math>=<span>1EE74</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x62A;</mtext></math>=<span>1EE75</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x62B;</mtext></math>=<span>1EE76</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x62E;</mtext></math>=<span>1EE77</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x636;</mtext></math>=<span>1EE79</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x638;</mtext></math>=<span>1EE7A</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x63A;</mtext></math>=<span>1EE7B</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x66E;</mtext></math>=<span>1EE7C</span></span>
+ <span><math class="testfont"><mtext mathvariant="stretched">&#x6A1;</mtext></math>=<span>1EE7E</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed-ref.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed-ref.html
new file mode 100644
index 0000000000..5e1461cd33
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant tailed (reference)</title>
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext>&#x1EE42;</mtext></math>=<span>1EE42</span></span>
+ <span><math class="testfont"><mtext>&#x1EE47;</mtext></math>=<span>1EE47</span></span>
+ <span><math class="testfont"><mtext>&#x1EE49;</mtext></math>=<span>1EE49</span></span>
+ <span><math class="testfont"><mtext>&#x1EE4B;</mtext></math>=<span>1EE4B</span></span>
+ <span><math class="testfont"><mtext>&#x1EE4D;</mtext></math>=<span>1EE4D</span></span>
+ <span><math class="testfont"><mtext>&#x1EE4E;</mtext></math>=<span>1EE4E</span></span>
+ <span><math class="testfont"><mtext>&#x1EE4F;</mtext></math>=<span>1EE4F</span></span>
+ <span><math class="testfont"><mtext>&#x1EE51;</mtext></math>=<span>1EE51</span></span>
+ <span><math class="testfont"><mtext>&#x1EE52;</mtext></math>=<span>1EE52</span></span>
+ <span><math class="testfont"><mtext>&#x1EE54;</mtext></math>=<span>1EE54</span></span><br/>
+ <span><math class="testfont"><mtext>&#x1EE57;</mtext></math>=<span>1EE57</span></span>
+ <span><math class="testfont"><mtext>&#x1EE59;</mtext></math>=<span>1EE59</span></span>
+ <span><math class="testfont"><mtext>&#x1EE5B;</mtext></math>=<span>1EE5B</span></span>
+ <span><math class="testfont"><mtext>&#x1EE5D;</mtext></math>=<span>1EE5D</span></span>
+ <span><math class="testfont"><mtext>&#x1EE5F;</mtext></math>=<span>1EE5F</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed.html b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed.html
new file mode 100644
index 0000000000..43fbca5e80
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mathml/mathvariant/mathvariant-tailed.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant tailed</title>
+<link rel="help" href="https://w3c.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://w3c.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+<link rel="help" href="https://w3c.github.io/mathml-core/#tailed-mappings">
+<link rel="match" href="mathvariant-tailed-ref.html"/>
+<meta name="assert" content="Verify that a single-char <mtext> with a tailed mathvariant is equivalent to an <mtext> with the transformed unicode character.">
+<style>
+ @font-face {
+ font-family: TestFont;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+ body > span {
+ padding: 10px;
+ }
+ span > span {
+ font-family: monospace;
+ font-size: 10px;
+ }
+ .testfont {
+ font-family: TestFont;
+ font-size: 10px;
+ }
+</style>
+<body>
+ <!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
+ <p>Test passes if all the equalities below are true.</p>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x62C;</mtext></math>=<span>1EE42</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x62D;</mtext></math>=<span>1EE47</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x64A;</mtext></math>=<span>1EE49</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x644;</mtext></math>=<span>1EE4B</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x646;</mtext></math>=<span>1EE4D</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x633;</mtext></math>=<span>1EE4E</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x639;</mtext></math>=<span>1EE4F</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x635;</mtext></math>=<span>1EE51</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x642;</mtext></math>=<span>1EE52</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x634;</mtext></math>=<span>1EE54</span></span><br/>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x62E;</mtext></math>=<span>1EE57</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x636;</mtext></math>=<span>1EE59</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x63A;</mtext></math>=<span>1EE5B</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x6BA;</mtext></math>=<span>1EE5D</span></span>
+ <span><math class="testfont"><mtext mathvariant="tailed">&#x66F;</mtext></math>=<span>1EE5F</span></span>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/media/2x2-green.ogv b/testing/web-platform/mozilla/tests/media/2x2-green.ogv
new file mode 100644
index 0000000000..29903c0a81
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/media/2x2-green.ogv
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/mediacapture-streams/MediaDevices-enumerateDevices.https.html b/testing/web-platform/mozilla/tests/mediacapture-streams/MediaDevices-enumerateDevices.https.html
new file mode 100644
index 0000000000..e7dcd4e531
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mediacapture-streams/MediaDevices-enumerateDevices.https.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+<head>
+<title>enumerateDevices: test that enumerateDevices is present (legacy Firefox)</title>
+<meta name='assert' content='Check that the enumerateDevices() method is present (legacy Firefox).'/>
+</head>
+<body>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This is a modified copy of
+testing/web-platform/tests/mediacapture-streams/MediaDevices-enumerateDevices.https.html
+testing legacy Firefox version of the <code>navigator.mediaDevices.enumerateDevices()</code> method.</p>
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<script src=permission-helper.js></script>
+<script>
+"use strict";
+
+promise_test(async () => {
+ assert_not_equals(navigator.mediaDevices.enumerateDevices, undefined, "navigator.mediaDevices.enumerateDevices exists");
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ for (const {kind, deviceId, label, groupId} of devices) {
+ assert_in_array(kind, ["videoinput", "audioinput", "audiooutput"]);
+ assert_greater_than(deviceId.length, 0, "deviceId should be present even if getUserMedia was never called successfully (legacy).");
+ assert_equals(label, "", "label should be empty string if getUserMedia was never called successfully.");
+ assert_greater_than(groupId.length, 0, "groupId should be present even if getUserMedia was never called successfully (legacy).");
+ }
+ assert_less_than_equal(devices.filter(({kind}) => kind == "audioinput").length,
+ 1, "there should be zero or one audio input device.");
+ assert_less_than_equal(devices.filter(({kind}) => kind == "videoinput").length,
+ 1, "there should be zero or one video input device.");
+ assert_equals(devices.filter(({kind}) => kind == "audiooutput").length,
+ 0, "there should be no audio output devices.");
+ assert_less_than_equal(devices.length, 2,
+ "there should be no more than two devices.");
+ if (devices.length > 1) {
+ assert_equals(devices[0].kind, "audioinput", "audioinput is first");
+ assert_equals(devices[1].kind, "videoinput", "videoinput is second");
+ }
+}, "mediaDevices.enumerateDevices() is present and working - before capture");
+
+promise_test(async t => {
+ await setMediaPermission("granted");
+ const stream = await navigator.mediaDevices.getUserMedia({ video: true });
+ stream.getTracks()[0].stop();
+
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ const kinds = ["audioinput", "videoinput"];
+ for (const {kind, deviceId} of devices) {
+ assert_in_array(kind, kinds, "camera doesn't expose audiooutput");
+ assert_equals(typeof deviceId, "string", "deviceId is a string.");
+ switch (kind) {
+ case "videoinput":
+ assert_greater_than(deviceId.length, 0, "video deviceId should not be empty.");
+ break;
+ case "audioinput":
+ assert_greater_than(deviceId.length, 0, "audio deviceId should not be empty (legacy).");
+ break;
+ }
+ }
+}, "mediaDevices.enumerateDevices() is working - after video capture");
+
+// This test is designed to come after its video counterpart directly above
+promise_test(async t => {
+ const devices1 = await navigator.mediaDevices.enumerateDevices();
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+ stream.getTracks()[0].stop();
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ assert_equals(devices.filter(({kind}) => kind == "videoinput").length,
+ devices1.filter(({kind}) => kind == "videoinput").length,
+ "same number of (previously exposed) videoinput devices");
+ assert_greater_than_equal(devices.filter(d => d.kind == "audioinput").length,
+ devices1.filter(d => d.kind == "audioinput").length,
+ "same number or more audioinput devices");
+ const order = ["audioinput", "videoinput", "audiooutput"];
+ for (const {kind, deviceId} of devices) {
+ assert_in_array(kind, order, "expected kind");
+ assert_equals(typeof deviceId, "string", "deviceId is a string.");
+ switch (kind) {
+ case "videoinput":
+ assert_greater_than(deviceId.length, 0, "video deviceId should not be empty.");
+ break;
+ case "audioinput":
+ assert_greater_than(deviceId.length, 0, "audio deviceId should not be empty.");
+ break;
+ }
+ }
+ const kinds = devices.map(({kind}) => kind);
+ const correct = [...kinds].sort((a, b) => order.indexOf(a) - order.indexOf(b));
+ assert_equals(JSON.stringify(kinds), JSON.stringify(correct), "correct order");
+}, "mediaDevices.enumerateDevices() is working - after video then audio capture");
+
+promise_test(async () => {
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ for (const mediaInfo of devices) {
+ if (mediaInfo.kind == "audioinput" || mediaInfo.kind == "videoinput") {
+ assert_true("InputDeviceInfo" in window, "InputDeviceInfo exists");
+ assert_true(mediaInfo instanceof InputDeviceInfo);
+ } else if (mediaInfo.kind == "audiooutput") {
+ assert_true(mediaInfo instanceof MediaDeviceInfo);
+ } else {
+ assert_unreached("mediaInfo.kind should be one of 'audioinput', 'videoinput', or 'audiooutput'.")
+ }
+ }
+}, "InputDeviceInfo is supported");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-in-background.https.html b/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-in-background.https.html
new file mode 100644
index 0000000000..55d1d24dce
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-in-background.https.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<title>enumerateDevices() in background tab with focus in chrome</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<body></body>
+<script>
+'use strict';
+// This test is not in cross-browser wpt because it uses Gecko-specific API
+// for focusing browser chrome and it assumes a specific tab browser design.
+// It assumes that
+// * browser chrome widget focus is associated with a single current document
+// presentation (tab),
+// https://github.com/w3c/mediacapture-main/issues/752#issuecomment-742036800
+// * window.open() focuses the new tab and makes the current tab hidden, and
+// * the opener tab becomes the current and visible tab again when the new tab
+// is closed.
+const blank_url = '/common/blank.html';
+
+function promise_event(target, name) {
+ return new Promise(resolve => target[`on${name}`] = resolve);
+}
+
+promise_test(async t => {
+ // Open a new tab, which is expected to receive focus and hide the first tab.
+ await test_driver.bless('window.open()');
+ assert_true(document.hasFocus(), 'This test needs focus on the browser.');
+ const promise_hidden = promise_event(document, 'visibilitychange');
+ const proxy = window.open(blank_url);
+ t.add_cleanup(() => proxy.close());
+ await Promise.all([
+ promise_hidden,
+ promise_event(proxy, 'focus'),
+ promise_event(proxy, 'load'),
+ ]);
+ assert_true(proxy.document.hasFocus(), 'proxy.document.hasFocus()');
+
+ await Promise.all([
+ promise_event(proxy, 'blur'),
+ SpecialPowers.spawnChrome([], function focus_url_bar() {
+ this.browsingContext.topChromeWindow.gURLBar.focus();
+ }),
+ ]);
+ assert_false(proxy.document.hasFocus(), 'proxy.document.hasFocus()');
+ assert_false(document.hasFocus(), 'document.hasFocus()');
+ assert_equals(document.visibilityState, 'hidden', 'visibilityState');
+
+ // Enumeration should remain pending while the first tab is background.
+ const promise_enumerate = navigator.mediaDevices.enumerateDevices();
+ // Enumerate in the foreground tab to confirm that URL bar focus is
+ // sufficient, and to provide enough time to check that the Promise from the
+ // background tab does not settle.
+ await proxy.navigator.mediaDevices.enumerateDevices();
+ // Race a settled Promise to check that the enumeration in the background tab
+ // has not settled.
+ const result = await Promise.race([promise_enumerate, 'pending']);
+ assert_equals(result, 'pending', 'pending Promise while background.');
+
+ // The enumeration Promise should resolve after the first tab returns to the
+ // foreground.
+ proxy.close();
+ await promise_event(document, 'visibilitychange');
+ assert_equals(document.visibilityState, 'visible', 'visibilityState');
+ await promise_enumerate;
+}, 'enumerateDevices in background');
+</script>
diff --git a/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-without-focus.https.html b/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-without-focus.https.html
new file mode 100644
index 0000000000..6516a514c5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mediacapture-streams/enumerateDevices-without-focus.https.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<title>enumerateDevices() without focus</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<body></body>
+<script>
+'use strict';
+const blank_url = '/common/blank.html';
+
+function promise_event(target, name) {
+ return new Promise(resolve => target[`on${name}`] = resolve);
+}
+// When testdriver.js supports switch-to-window, it can replace this function
+// and this test can be upstreamed.
+// https://github.com/web-platform-tests/wpt/issues/10666
+function switch_toplevel_focus_for_window(win) {
+ return win.SpecialPowers.spawnChrome([], function activate_browser_window() {
+ this.browsingContext.topChromeWindow.focus();
+ });
+}
+
+promise_test(async t => {
+ await test_driver.bless('window.open()');
+ assert_true(document.hasFocus(), 'This test needs focus on the document.');
+ const promise_blur = promise_event(window, 'blur');
+ // 'resizable' is requested for a separate OS window on relevant platforms
+ // so that this test tests OS focus changes rather than document visibility.
+ const proxy = window.open(blank_url, '', 'resizable');
+ t.add_cleanup(() => proxy.close());
+ await Promise.all([
+ promise_blur,
+ switch_toplevel_focus_for_window(proxy),
+ promise_event(proxy, 'load'),
+ ]);
+ assert_false(document.hasFocus(), 'document.hasFocus() after blur');
+
+ // Enumeration should remain pending without focus.
+ const promise_enumerate = navigator.mediaDevices.enumerateDevices();
+ // Enumerate in the focused window to provide enough time to check that
+ // the Promise from the unfocused window does not settle.
+ await proxy.navigator.mediaDevices.enumerateDevices();
+ // Race a settled Promise to check that the enumeration in the first window
+ // has not settled.
+ const result = await Promise.race([promise_enumerate, 'pending']);
+ assert_equals(result, 'pending', 'pending Promise without focus.');
+
+ // The enumeration Promise should resolve after focus returns to the window.
+ proxy.close();
+ await Promise.all([
+ promise_event(window, 'focus'),
+ switch_toplevel_focus_for_window(window),
+ ]);
+ assert_true(document.hasFocus(), 'document.hasFocus() after focus');
+ await promise_enumerate;
+}, 'enumerateDevices without focus');
+</script>
diff --git a/testing/web-platform/mozilla/tests/mediacapture-streams/permission-helper.js b/testing/web-platform/mozilla/tests/mediacapture-streams/permission-helper.js
new file mode 100644
index 0000000000..0a237f7d43
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/mediacapture-streams/permission-helper.js
@@ -0,0 +1,24 @@
+// Set permissions for camera and microphone using Web Driver
+// Status can be one of "granted" or "denied"
+// Scope take values from permission names
+async function setMediaPermission(status="granted", scope=["camera", "microphone"]) {
+ try {
+ for (let s of scope) {
+ await test_driver.set_permission({ name: s }, status);
+ }
+ } catch (e) {
+ const noSetPermissionSupport = typeof e === "string" && e.match(/set_permission not implemented/);
+ if (!(noSetPermissionSupport ||
+ (e instanceof Error && e.message.match("unimplemented")) )) {
+ throw e;
+ }
+ // Web Driver not implemented action
+ // FF: https://bugzilla.mozilla.org/show_bug.cgi?id=1524074
+
+ // with current WPT runners, will default to granted state for FF and Safari
+ // throw if status!="granted" to invalidate test results
+ if (status === "denied") {
+ assert_implements_optional(!noSetPermissionSupport, "Unable to set permission to denied for this test");
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/placeholder b/testing/web-platform/mozilla/tests/placeholder
new file mode 100644
index 0000000000..92dd3d5151
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/placeholder
@@ -0,0 +1,6 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+This is a placeholder file to ensure that this directory remains
+in source control and test packages even when it is otherwise empty. \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/screen-capture/getdisplaymedia-user-activation-consumed.https.html b/testing/web-platform/mozilla/tests/screen-capture/getdisplaymedia-user-activation-consumed.https.html
new file mode 100644
index 0000000000..d0623fbaa5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/screen-capture/getdisplaymedia-user-activation-consumed.https.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<head>
+<title>Test getDisplayMedia() after user activation is consumed</title>
+<link rel="help" href="https://w3c.github.io/mediacapture-screen-share/#dom-mediadevices-getdisplaymedia">
+</head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+'use strict';
+
+promise_test(async t => {
+ await test_driver.bless('transient activation');
+ // SpecialPowers is used to consume user activation because the only
+ // spec-compliant Gecko API that consumes user activation is
+ // navigator.share(), which is disabled on CI versions of WINNT.
+ // https://searchfox.org/mozilla-central/rev/66547980e8e8ca583473c74f207cae5bac1ed541/testing/web-platform/meta/web-share/share-consume-activation.https.html.ini#4
+ const had_transient_activation =
+ SpecialPowers.wrap(document).consumeTransientUserGestureActivation();
+ assert_true(had_transient_activation,
+ 'should have had transient activation');
+ const p = navigator.mediaDevices.getDisplayMedia();
+ // Race a settled promise to check that the returned promise is already
+ // rejected.
+ await promise_rejects_dom(
+ t, 'InvalidStateError', Promise.race([p, Promise.resolve()]),
+ 'getDisplayMedia should have returned an already-rejected promise.');
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/selection/Selection-addRange-same-instance.html b/testing/web-platform/mozilla/tests/selection/Selection-addRange-same-instance.html
new file mode 100644
index 0000000000..c374b8ecdf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/selection/Selection-addRange-same-instance.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+"use strict";
+
+promise_test(async () => {
+ await new Promise(resolve => document.addEventListener("DOMContentLoaded", resolve));
+
+ getSelection().removeAllRanges();
+ const range = document.createRange();
+ range.setStart(document.querySelector("span"), 0);
+ getSelection().addRange(range);
+ getSelection().addRange(range);
+ assert_equals(getSelection().rangeCount, 1, "Adding same collapsed range twice should not clone the range");
+ assert_equals(getSelection().getRangeAt(0), range, "The first range should be the added range");
+ assert_equals(getSelection().focusNode, document.querySelector("span"), "Focus node should be the <span>");
+ assert_equals(getSelection().focusOffset, 0, "Focus offset should be 0");
+ assert_true(getSelection().isCollapsed, "Selection should be collapsed");
+}, "Adding same collapsed range should not change selections");
+
+promise_test(async () => {
+ getSelection().removeAllRanges();
+ const range = document.createRange();
+ range.selectNodeContents(document.querySelector("div"));
+ getSelection().addRange(range);
+ getSelection().addRange(range);
+ assert_equals(getSelection().rangeCount, 1, "Adding same range twice should not clone the range");
+ assert_equals(getSelection().getRangeAt(0), range, "The first range should be the added range");
+ assert_equals(getSelection().anchorNode, document.querySelector("div"), "Anchor node should be the <div>");
+ assert_equals(getSelection().anchorOffset, 0, "Anchor offset should be 0");
+ assert_equals(getSelection().focusNode, document.querySelector("div"), "Focus node should be the <div>");
+ assert_equals(getSelection().focusOffset, 1, "Focus offset should be 1");
+}, "Adding non-collapsed range after updating the range should not change selections");
+
+promise_test(async () => {
+ getSelection().removeAllRanges();
+ const range = document.createRange();
+ range.collapse(document.querySelector("span"), 0);
+ getSelection().addRange(range);
+ range.selectNodeContents(document.querySelector("div"));
+ getSelection().addRange(range);
+ assert_equals(getSelection().rangeCount, 1, "Adding same range twice should not clone the range");
+ assert_equals(getSelection().getRangeAt(0), range, "The first range should be the added range");
+ assert_equals(getSelection().anchorNode, document.querySelector("div"), "Anchor node should be the <div>");
+ assert_equals(getSelection().anchorOffset, 0, "Anchor offset should be 0");
+ assert_equals(getSelection().focusNode, document.querySelector("div"), "Focus node should be the <div>");
+ assert_equals(getSelection().focusOffset, 1, "Focus offset should be 1");
+}, "Adding same collapsed range after updating the range should not change selections");
+</script>
+</head>
+<body><div><span></span></div></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html b/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html
new file mode 100644
index 0000000000..e093f616c1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/bug1675097.https.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Controlled iframe with initial about:blank becomes sandboxed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<body>
+<script>
+
+// This test creates an iframe controlled by a service worker, which in turn has
+// another iframe in it. The inner iframe's fetch is intercepted by the service
+// worker, which notifies the outer iframe, which then adds the sandbox
+// attribute to the inner iframe. The outer iframe then signals the service
+// worker that it should evaluate self.clients.matchAll() and finally respond to
+// the inner iframe's fetch.
+// Evaluating self.clients.matchAll() causes the creation of the initial
+// about:blank document for the inner iframe, and if the sandboxing flags used
+// for that document are not the original flags for the inner iframe (i.e. none)
+// then the document will have an opaque origin, a case that we need to handle
+// properly.
+promise_test(async t => {
+ const URL = 'resources/bug1675097-sw.js';
+ const SCOPE = 'resources/';
+
+ const registration = await service_worker_unregister_and_register(t, URL, SCOPE);
+ t.add_cleanup(() => registration.unregister());
+
+ await wait_for_state(t, registration.installing, 'activated');
+
+ const outer = await with_iframe(SCOPE + 'bug1675097-iframe.html');
+ t.add_cleanup(() => outer.remove());
+}, 'Regression test for bug 1675097');
+
+</script>
+</body>
diff --git a/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html b/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html
new file mode 100644
index 0000000000..245522f5fc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/no_intercept_for_crossorigin_media.https.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Don't intercept cross-origin media requests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js">
+</script>
+<body>
+<script>
+
+'use strict';
+
+const scope = './resources/';
+
+/**
+ * Ensure service workers don't intercept cross-origin media range requests.
+ */
+promise_test(async t => {
+ const registration = await service_worker_unregister_and_register(
+ t, scope + 'intercept_media_sw.js', scope);
+ t.add_cleanup(() => registration.unregister());
+ await wait_for_state(t, registration.installing, 'activated');
+
+ const frame = await with_iframe(scope + 'crossorigin_media_iframe.html');
+ return frame.contentWindow.create_media_promise()
+}, 'Service worker does not intercept a cross-origin media range request');
+
+/**
+ * Ensure service workers do intercept cross-origin media non-range requests.
+ */
+promise_test(async t => {
+ const registration = await service_worker_unregister_and_register(
+ t, scope + 'intercept_media_sw.js', scope);
+ t.add_cleanup(() => registration.unregister());
+ await wait_for_state(t, registration.installing, 'activated');
+
+ const frame = await with_iframe(scope + 'crossorigin_media_iframe_nonrange.html');
+ return frame.contentWindow.create_media_promise()
+}, 'Service worker intercepts a cross-origin non-range media request');
+
+</script>
+</body>
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/blank.html b/testing/web-platform/mozilla/tests/service-workers/resources/blank.html
new file mode 100644
index 0000000000..a3c3a4689a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/blank.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<title>Empty doc</title>
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html
new file mode 100644
index 0000000000..5ad7b95594
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-iframe.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<body>
+<script>
+let channel = new MessageChannel();
+channel.port1.onmessage = event => {
+ if (event.data === 'intercepted') {
+ const iframe = document.querySelector('iframe');
+ iframe.sandbox = '';
+ navigator.serviceWorker.controller.postMessage({ type: 'ack' });
+ }
+};
+navigator.serviceWorker.controller.postMessage({ type: 'register', port: channel.port2 }, [channel.port2]);
+</script>
+<iframe src='inner'></iframe>
+</body>
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js
new file mode 100644
index 0000000000..e2894e1032
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/bug1675097-sw.js
@@ -0,0 +1,26 @@
+// We use promises because the message and fetch events do not have a guaranteed
+// order, since they come from different task sources.
+var resolvePortPromise;
+var portPromise = new Promise(resolve => resolvePortPromise = resolve);
+var resolveResolveResponsePromise;
+var resolveResponsePromise = new Promise(resolve => resolveResolveResponsePromise = resolve);
+
+self.addEventListener('fetch', event => {
+ if (event.request.url.indexOf('inner') !== -1) {
+ event.respondWith(new Promise(resolve => {
+ resolveResolveResponsePromise(resolve);
+ }));
+ portPromise.then(port => port.postMessage('intercepted'));
+ }
+});
+
+self.addEventListener('message', event => {
+ if (event.data.type === 'register') {
+ resolvePortPromise(event.data.port);
+ }
+ else if (event.data.type === 'ack') {
+ self.clients.matchAll()
+ .then(() => resolveResponsePromise)
+ .then(resolveResponse => resolveResponse(new Response('inner iframe')));
+ }
+});
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html
new file mode 100644
index 0000000000..54cdcaa8dd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<body>
+<script>
+
+'use strict';
+
+function remoteize(relpath) {
+ let curdir = location.href.replace(/\/[^\/]*$/, '/')
+ return curdir.replace('://', '://www1.') + relpath
+}
+
+function create_media_promise() {
+ return new Promise((resolve, reject) => {
+ let video = document.createElement('video')
+ video.autoplay = true
+ video.muted = true
+ video.onplay = () => resolve('ok')
+ video.onerror = () => reject('video error')
+ video.src = remoteize('fetch_video.py')
+ })
+}
+
+</script>
+</body>
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html
new file mode 100644
index 0000000000..8e3c20fdeb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/crossorigin_media_iframe_nonrange.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<body>
+<script>
+
+'use strict';
+
+function remoteize(relpath) {
+ let curdir = location.href.replace(/\/[^\/]*$/, '/')
+ return curdir.replace('://', '://www1.') + relpath
+}
+
+function create_media_promise() {
+ return new Promise((resolve, reject) => {
+ let image = document.createElement('img')
+ image.onload = () => resolve('ok')
+ image.onerror = () => reject('image error')
+ image.src = remoteize('blank.html') // sw will replace with an image
+ })
+}
+
+</script>
+</body>
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/empty.js b/testing/web-platform/mozilla/tests/service-workers/resources/empty.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/empty.js
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py b/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py
new file mode 100644
index 0000000000..541f00c019
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/fetch_video.py
@@ -0,0 +1,14 @@
+import os
+
+
+def main(request, response):
+ filename = os.path.join(request.doc_root, u"media", u"2x2-green.ogv")
+ body = open(filename, "rb").read()
+ length = len(body)
+ headers = [
+ (b"Content-Type", b"video/ogg"),
+ (b"Accept-Ranges", b"bytes"),
+ (b"Content-Length", b"%d" % length),
+ (b"Content-Range", b"bytes 0-%d/%d" % (length - 1, length)),
+ ]
+ return headers, body
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/green.png b/testing/web-platform/mozilla/tests/service-workers/resources/green.png
new file mode 100644
index 0000000000..28a1faab37
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/green.png
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js b/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js
new file mode 100644
index 0000000000..6c373aa0de
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/resources/intercept_media_sw.js
@@ -0,0 +1,14 @@
+'use strict';
+
+self.addEventListener('fetch', event => {
+ if (event.request.url.indexOf('fetch_video.py') !== -1) {
+ // A no-cors media range request /should not/ be intercepted.
+ // Respond with some text to cause an error.
+ event.respondWith(new Response('intercepted'));
+ }
+ else if (event.request.url.indexOf('blank.html') !== -1) {
+ // A no-cors media non-range request /should/ be intercepted.
+ // Respond with an image to avoid an error.
+ event.respondWith(fetch('green.png'));
+ }
+});
diff --git a/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html b/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html
new file mode 100644
index 0000000000..371fa81161
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/service-workers/update_completes_in_disconnected_global.https.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>Service Worker: Disconnected Global Update()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+'use strict';
+
+/**
+ * Gecko-only pseudo-crash-test to verify that if we call
+ * ServiceWorkerRegistration.update() from a global that will be destroyed
+ * before any IPC call could return that we don't crash.
+ *
+ * We use an iframe to create a global that we can destroy on demand.
+ */
+promise_test(async function(t) {
+ const scope = 'resources/blank.html';
+ const sw_url = 'resources/empty.js';
+
+ let reg = await service_worker_unregister_and_register(t, sw_url, scope);
+ t.add_cleanup(function() {
+ return service_worker_unregister(t, scope);
+ });
+
+ // Wait for the worker to be activated so that we are in a known state.
+ await wait_for_state(t, reg.installing, 'activated');
+
+ let f = await with_iframe(scope);
+ let f_global = f.contentWindow;
+ // The frame should be controlled, although it's not necessary for the test.
+ assert_true(!!f_global.navigator.serviceWorker.controller);
+ t.add_cleanup(function() {
+ if (f) {
+ f.remove();
+ }
+ });
+
+ // Get a registration object that lives in the iframe's global.
+ let f_reg = await f_global.navigator.serviceWorker.getRegistration(reg.scope);
+ assert_true(!!f_reg, 'got registration');
+ assert_equals(reg.scope, f_reg.scope, 'Right registration');
+
+ // Trigger the update and destroy the global.
+ let update_resolved = false;
+ let update_rejected = false;
+
+ let update_promise = f_reg.update();
+ update_promise.then(
+ () => { update_resolved = true; }, () => { update_rejected = true; });
+
+ f.remove();
+ f = null;
+ f_global = null;
+
+ // Now we want to wait on an update call that should fire strictly after the
+ // update call above.
+ await reg.update();
+
+ assert_false(update_resolved, "frame update() should not have resolved");
+ assert_true(update_rejected, "frame update() should have rejected");
+}, 'ServiceWorkerRegistration.update() concluding in a disconnected global');
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/svg/smil-sampling.html b/testing/web-platform/mozilla/tests/svg/smil-sampling.html
new file mode 100644
index 0000000000..8eecb63595
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/svg/smil-sampling.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg width="100" height="100">
+ <rect width="100" height="100" fill="blue">
+ <animate attributeName="fill" from="brown" to="red" dur="1000s"/>
+ </rect>
+</svg>
+<script>
+function isSampling() {
+ return SpecialPowers.wrap(window).windowUtils.refreshDriverHasPendingTick;
+}
+function tick() {
+ return new Promise(r => {
+ requestAnimationFrame(() => requestAnimationFrame(r));
+ });
+}
+
+// See comment in layout/base/tests/test_bug1756118.html about why the timeouts
+// etc.
+async function expectTicksToStop() {
+ for (let i = 0; i < 100; i++) {
+ await new Promise(r => setTimeout(r, 8));
+ if(!isSampling()) {
+ break;
+ }
+ }
+ assert_false(isSampling(), "refresh driver should have eventually stopped ticking");
+}
+
+promise_test(async function(t) {
+ await tick();
+ assert_true(isSampling(), "Animation should be running");
+ let svg = document.querySelector("svg");
+ svg.remove();
+ await tick();
+ await expectTicksToStop();
+
+ document.body.appendChild(svg);
+ await tick();
+ assert_true(isSampling(), "Animation should be running again");
+});
+</script>
diff --git a/testing/web-platform/mozilla/tests/web-animations/web-animations-print-ref.html b/testing/web-platform/mozilla/tests/web-animations/web-animations-print-ref.html
new file mode 100644
index 0000000000..539d072d16
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/web-animations/web-animations-print-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE HTML>
+<html>
+<title>Web animation</title>
+<p style="color: blue">blue with animation support; olive without</p>
diff --git a/testing/web-platform/mozilla/tests/web-animations/web-animations-print.html b/testing/web-platform/mozilla/tests/web-animations/web-animations-print.html
new file mode 100644
index 0000000000..2b1ed19eb6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/web-animations/web-animations-print.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<link rel="help" href="https://drafts.csswg.org/web-animations/">
+<link rel="match" href="web-animations-print-ref.html">
+<title>Web animation</title>
+<p id="anim" style="color: olive">blue with animation support; olive without</p>
+<script>
+const animationData = [
+ {"color":"#0000FF"},
+ {"color":"#0000FF"}
+];
+
+const animationTiming = {
+ "duration":1,
+ "iterations":Infinity
+};
+
+let element = document.getElementById("anim");
+element.animate(animationData, animationTiming);
+</script>
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py
new file mode 100644
index 0000000000..910b202075
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/__init__.py
@@ -0,0 +1,20 @@
+import contextlib
+
+
+def set_context(session, context):
+ session.send_session_command("POST", "moz/context", {"context": context})
+
+
+@contextlib.contextmanager
+def using_context(session, context):
+ orig_context = session.send_session_command("GET", "moz/context")
+ needs_change = context != orig_context
+
+ if needs_change:
+ set_context(session, context)
+
+ try:
+ yield
+ finally:
+ if needs_change:
+ set_context(session, orig_context)
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py
new file mode 100644
index 0000000000..1a5906339b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/reference_context.py
@@ -0,0 +1,72 @@
+import pytest
+
+from . import using_context
+
+pytestmark = pytest.mark.asyncio
+
+
+# Helper to assert the order of top level browsing contexts.
+# The window used for the assertion is inferred from the first context id of
+# expected_context_ids.
+def assert_tab_order(session, expected_context_ids):
+ with using_context(session, "chrome"):
+ context_ids = session.execute_script(
+ """
+ const contextId = arguments[0];
+ const { TabManager } =
+ ChromeUtils.importESModule("chrome://remote/content/shared/TabManager.sys.mjs");
+ const browsingContext = TabManager.getBrowsingContextById(contextId);
+ const chromeWindow = browsingContext.embedderElement.ownerGlobal;
+ const tabBrowser = TabManager.getTabBrowser(chromeWindow);
+ return tabBrowser.browsers.map(browser => TabManager.getIdForBrowser(browser));
+ """,
+ args=(expected_context_ids[0],),
+ )
+
+ assert context_ids == expected_context_ids
+
+
+async def test_reference_context(bidi_session, current_session):
+ # Create a new window with a tab tab1
+ result = await bidi_session.browsing_context.create(type_hint="window")
+ tab1_context_id = result["context"]
+
+ # Create a second window with a tab tab2
+ result = await bidi_session.browsing_context.create(type_hint="window")
+ tab2_context_id = result["context"]
+
+ # Create a new tab tab3 next to tab1
+ result = await bidi_session.browsing_context.create(
+ type_hint="tab", reference_context=tab1_context_id
+ )
+ tab3_context_id = result["context"]
+
+ # Create a new tab tab4 next to tab2
+ result = await bidi_session.browsing_context.create(
+ type_hint="tab", reference_context=tab2_context_id
+ )
+ tab4_context_id = result["context"]
+
+ # Create a new tab tab5 also next to tab2 (should consequently be between
+ # tab2 and tab4)
+ result = await bidi_session.browsing_context.create(
+ type_hint="tab", reference_context=tab2_context_id
+ )
+ tab5_context_id = result["context"]
+
+ # Create a new window, but pass a reference_context from an existing window.
+ # The reference context is expected to be ignored here.
+ result = await bidi_session.browsing_context.create(
+ type_hint="window", reference_context=tab2_context_id
+ )
+ tab6_context_id = result["context"]
+
+ # We expect 3 windows in total, with a specific tab order:
+ # - the first window should contain tab1, tab3
+ assert_tab_order(current_session, [tab1_context_id, tab3_context_id])
+ # - the second window should contain tab2, tab5, tab4
+ assert_tab_order(
+ current_session, [tab2_context_id, tab5_context_id, tab4_context_id]
+ )
+ # - the third window should contain tab6
+ assert_tab_order(current_session, [tab6_context_id])
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py
new file mode 100644
index 0000000000..337a03b3dd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/create/type_hint.py
@@ -0,0 +1,31 @@
+import pytest
+from tests.support.asserts import assert_success
+
+from . import using_context
+
+pytestmark = pytest.mark.asyncio
+
+
+def count_window_handles(session):
+ with using_context(session, "chrome"):
+ response = session.transport.send(
+ "GET", "session/{session_id}/window/handles".format(**vars(session))
+ )
+ chrome_handles = assert_success(response)
+ return len(chrome_handles)
+
+
+@pytest.mark.parametrize("type_hint", ["tab", "window"])
+async def test_type_hint(bidi_session, current_session, type_hint):
+ assert len(await bidi_session.browsing_context.get_tree()) == 1
+ assert count_window_handles(current_session) == 1
+
+ await bidi_session.browsing_context.create(type_hint=type_hint)
+
+ if type_hint == "window":
+ expected_window_count = 2
+ else:
+ expected_window_count = 1
+
+ assert len(await bidi_session.browsing_context.get_tree()) == 2
+ assert count_window_handles(current_session) == expected_window_count
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py
new file mode 100644
index 0000000000..374359d1ae
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/browsing_context/navigate/error.py
@@ -0,0 +1,48 @@
+import os
+from copy import deepcopy
+
+import pytest
+from tests.bidi.browsing_context.navigate import navigate_and_assert
+
+pytestmark = pytest.mark.asyncio
+
+
+async def test_insecure_certificate(configuration, url, custom_profile, geckodriver):
+ try:
+ # Create a new profile and remove the certificate storage so that
+ # loading a HTTPS page will cause an insecure certificate error
+ os.remove(os.path.join(custom_profile.profile, "cert9.db"))
+ except Exception:
+ pass
+
+ config = deepcopy(configuration)
+ config["capabilities"]["moz:firefoxOptions"]["args"] = [
+ "--profile",
+ custom_profile.profile,
+ ]
+ # Capability matching not implemented yet for WebDriver BiDi (bug 1713784)
+ config["capabilities"]["acceptInsecureCerts"] = False
+ config["capabilities"]["webSocketUrl"] = True
+
+ driver = geckodriver(config=config)
+ driver.new_session()
+
+ bidi_session = driver.session.bidi_session
+ await bidi_session.start()
+
+ contexts = await bidi_session.browsing_context.get_tree(max_depth=0)
+ await navigate_and_assert(
+ bidi_session,
+ contexts[0],
+ url("/common/blank.html", protocol="https"),
+ expected_error=True,
+ )
+
+
+async def test_invalid_content_encoding(bidi_session, new_tab, inline):
+ await navigate_and_assert(
+ bidi_session,
+ new_tab,
+ f"{inline('<div>foo')}&pipe=header(Content-Encoding,gzip)",
+ expected_error=True,
+ )
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py
new file mode 100644
index 0000000000..69b1f2fb7a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/errors/errors.py
@@ -0,0 +1,8 @@
+import pytest
+from webdriver.bidi.error import UnknownCommandException
+
+
+@pytest.mark.asyncio
+async def test_internal_method(bidi_session, send_blocking_command):
+ with pytest.raises(UnknownCommandException):
+ await send_blocking_command("log._applySessionData", {})
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py
new file mode 100644
index 0000000000..561b80d120
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/interface/interface.py
@@ -0,0 +1,26 @@
+import pytest
+from webdriver.bidi.client import BidiSession
+from webdriver.bidi.modules.script import ContextTarget
+
+pytestmark = pytest.mark.asyncio
+
+
+async def test_navigator_webdriver_enabled(inline, browser):
+ # Request a new browser with only WebDriver BiDi and not Marionette/CDP enabled.
+ current_browser = browser(use_bidi=True, extra_prefs={"remote.active-protocols": 1})
+ server_host = current_browser.remote_agent_host
+ server_port = current_browser.remote_agent_port
+
+ async with BidiSession.bidi_only(
+ f"ws://{server_host}:{server_port}"
+ ) as bidi_session:
+ contexts = await bidi_session.browsing_context.get_tree(max_depth=0)
+ assert len(contexts) > 0
+
+ result = await bidi_session.script.evaluate(
+ expression="navigator.webdriver",
+ target=ContextTarget(contexts[0]["context"]),
+ await_promise=False,
+ )
+
+ assert result == {"type": "boolean", "value": True}
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py b/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py
new file mode 100644
index 0000000000..43bccdb845
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/script/exception_details.py
@@ -0,0 +1,69 @@
+import pytest
+from webdriver.bidi.modules.script import ContextTarget, ScriptEvaluateResultException
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize("await_promise", [True, False])
+@pytest.mark.parametrize(
+ "expression",
+ [
+ "null",
+ "{ toString: 'not a function' }",
+ "{ toString: () => {{ throw 'toString not allowed'; }} }",
+ "{ toString: () => true }",
+ ],
+)
+@pytest.mark.asyncio
+async def test_call_function_without_to_string_interface(
+ bidi_session, top_context, await_promise, expression
+):
+ function_declaration = "()=>{throw { toString: 'not a function' } }"
+ if await_promise:
+ function_declaration = "async" + function_declaration
+
+ with pytest.raises(ScriptEvaluateResultException) as exception:
+ await bidi_session.script.call_function(
+ function_declaration=function_declaration,
+ await_promise=await_promise,
+ target=ContextTarget(top_context["context"]),
+ )
+
+ assert "exceptionDetails" in exception.value.result
+ exceptionDetails = exception.value.result["exceptionDetails"]
+
+ assert "text" in exceptionDetails
+ assert isinstance(exceptionDetails["text"], str)
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize("await_promise", [True, False])
+@pytest.mark.parametrize(
+ "expression",
+ [
+ "null",
+ "{ toString: 'not a function' }",
+ "{ toString: () => {{ throw 'toString not allowed'; }} }",
+ "{ toString: () => true }",
+ ],
+)
+@pytest.mark.asyncio
+async def test_evaluate_without_to_string_interface(
+ bidi_session, top_context, await_promise, expression
+):
+ if await_promise:
+ expression = f"Promise.reject({expression})"
+ else:
+ expression = f"throw {expression}"
+
+ with pytest.raises(ScriptEvaluateResultException) as exception:
+ await bidi_session.script.evaluate(
+ expression=expression,
+ await_promise=await_promise,
+ target=ContextTarget(top_context["context"]),
+ )
+
+ assert "exceptionDetails" in exception.value.result
+ exceptionDetails = exception.value.result["exceptionDetails"]
+
+ assert "text" in exceptionDetails
+ assert isinstance(exceptionDetails["text"], str)
diff --git a/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py b/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py
new file mode 100644
index 0000000000..e5ebfa1eb0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/bidi/websocket_upgrade.py
@@ -0,0 +1,156 @@
+import pytest
+from support.network import get_host, websocket_request
+
+
+@pytest.mark.parametrize(
+ "hostname, port_type, status",
+ [
+ # Valid hosts
+ ("localhost", "server_port", 101),
+ ("localhost", "default_port", 101),
+ ("127.0.0.1", "server_port", 101),
+ ("127.0.0.1", "default_port", 101),
+ ("[::1]", "server_port", 101),
+ ("[::1]", "default_port", 101),
+ ("192.168.8.1", "server_port", 101),
+ ("192.168.8.1", "default_port", 101),
+ ("[fdf8:f535:82e4::53]", "server_port", 101),
+ ("[fdf8:f535:82e4::53]", "default_port", 101),
+ # Invalid hosts
+ ("mozilla.org", "server_port", 400),
+ ("mozilla.org", "wrong_port", 400),
+ ("mozilla.org", "default_port", 400),
+ ("localhost", "wrong_port", 400),
+ ("127.0.0.1", "wrong_port", 400),
+ ("[::1]", "wrong_port", 400),
+ ("192.168.8.1", "wrong_port", 400),
+ ("[fdf8:f535:82e4::53]", "wrong_port", 400),
+ ],
+ ids=[
+ # Valid hosts
+ "localhost with same port as RemoteAgent",
+ "localhost with default port",
+ "127.0.0.1 (loopback) with same port as RemoteAgent",
+ "127.0.0.1 (loopback) with default port",
+ "[::1] (ipv6 loopback) with same port as RemoteAgent",
+ "[::1] (ipv6 loopback) with default port",
+ "ipv4 address with same port as RemoteAgent",
+ "ipv4 address with default port",
+ "ipv6 address with same port as RemoteAgent",
+ "ipv6 address with default port",
+ # Invalid hosts
+ "random hostname with the same port as RemoteAgent",
+ "random hostname with a different port than RemoteAgent",
+ "random hostname with default port",
+ "localhost with a different port than RemoteAgent",
+ "127.0.0.1 (loopback) with a different port than RemoteAgent",
+ "[::1] (ipv6 loopback) with a different port than RemoteAgent",
+ "ipv4 address with a different port than RemoteAgent",
+ "ipv6 address with a different port than RemoteAgent",
+ ],
+)
+def test_host_header(browser, hostname, port_type, status):
+ # Request a default browser
+ current_browser = browser(use_bidi=True)
+ server_host = current_browser.remote_agent_host
+ server_port = current_browser.remote_agent_port
+ test_host = get_host(port_type, hostname, server_port)
+
+ response = websocket_request(server_host, server_port, host=test_host)
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "hostname, port_type, status",
+ [
+ # Allowed hosts
+ ("testhost", "server_port", 101),
+ ("testhost", "default_port", 101),
+ ("testhost", "wrong_port", 400),
+ # IP addresses
+ ("192.168.8.1", "server_port", 101),
+ ("192.168.8.1", "default_port", 101),
+ ("[fdf8:f535:82e4::53]", "server_port", 101),
+ ("[fdf8:f535:82e4::53]", "default_port", 101),
+ ("127.0.0.1", "server_port", 101),
+ ("127.0.0.1", "default_port", 101),
+ ("[::1]", "server_port", 101),
+ ("[::1]", "default_port", 101),
+ # Localhost
+ ("localhost", "server_port", 400),
+ ("localhost", "default_port", 400),
+ ],
+ ids=[
+ # Allowed hosts
+ "allowed host with same port as RemoteAgent",
+ "allowed host with default port",
+ "allowed host with wrong port",
+ # IP addresses
+ "ipv4 address with same port as RemoteAgent",
+ "ipv4 address with default port",
+ "ipv6 address with same port as RemoteAgent",
+ "ipv6 address with default port",
+ "127.0.0.1 (loopback) with same port as RemoteAgent",
+ "127.0.0.1 (loopback) with default port",
+ "[::1] (ipv6 loopback) with same port as RemoteAgent",
+ "[::1] (ipv6 loopback) with default port",
+ # Localhost
+ "localhost with same port as RemoteAgent",
+ "localhost with default port",
+ ],
+)
+def test_allowed_hosts(browser, hostname, port_type, status):
+ # Request a browser with custom allowed hosts.
+ current_browser = browser(
+ use_bidi=True,
+ extra_args=["--remote-allow-hosts", "testhost"],
+ )
+ server_host = current_browser.remote_agent_host
+ server_port = current_browser.remote_agent_port
+ test_host = get_host(port_type, hostname, server_port)
+
+ response = websocket_request(server_host, server_port, host=test_host)
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "origin, status",
+ [
+ (None, 101),
+ ("", 400),
+ ("sometext", 400),
+ ("http://localhost:1234", 400),
+ ],
+)
+def test_origin_header(browser, origin, status):
+ # Request a default browser.
+ current_browser = browser(use_bidi=True)
+ server_host = current_browser.remote_agent_host
+ server_port = current_browser.remote_agent_port
+ response = websocket_request(server_host, server_port, origin=origin)
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "origin, status",
+ [
+ (None, 101),
+ ("", 400),
+ ("sometext", 400),
+ ("http://localhost:1234", 101),
+ ("https://localhost:1234", 400),
+ ],
+)
+def test_allowed_origins(browser, origin, status):
+ # Request a browser with custom allowed origins.
+ current_browser = browser(
+ use_bidi=True,
+ extra_args=["--remote-allow-origins", "http://localhost:1234"],
+ )
+ server_port = current_browser.remote_agent_port
+
+ # Both `localhost` and `127.0.0.1` have to accept connections.
+ for target_host in ["127.0.0.1", "localhost"]:
+ print(f"Connecting to the WebSocket via host {target_host}")
+ response = websocket_request(target_host, server_port, origin=origin)
+ assert response.status == status
diff --git a/testing/web-platform/mozilla/tests/webdriver/cdp/__init__.py b/testing/web-platform/mozilla/tests/webdriver/cdp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/cdp/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/cdp/debugger_address.py b/testing/web-platform/mozilla/tests/webdriver/cdp/debugger_address.py
new file mode 100644
index 0000000000..ef9a301d24
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/cdp/debugger_address.py
@@ -0,0 +1,45 @@
+# META: timeout=long
+
+import json
+
+import pytest
+from support.context import using_context
+from tests.support.http_request import HTTPRequest
+
+
+def test_debugger_address_not_set(session):
+ debugger_address = session.capabilities.get("moz:debuggerAddress")
+ assert debugger_address is None
+
+
+@pytest.mark.capabilities({"moz:debuggerAddress": False})
+def test_debugger_address_false(session):
+ debugger_address = session.capabilities.get("moz:debuggerAddress")
+ assert debugger_address is None
+
+
+@pytest.mark.capabilities({"moz:debuggerAddress": True})
+@pytest.mark.parametrize("fission_enabled", [True, False], ids=["enabled", "disabled"])
+def test_debugger_address_true_with_fission(session, fission_enabled):
+ debugger_address = session.capabilities.get("moz:debuggerAddress")
+ assert debugger_address is not None
+
+ host, port = debugger_address.split(":")
+ assert host == "127.0.0.1"
+ assert port.isnumeric()
+
+ # Fetch the browser version via the debugger address, `localhost` has
+ # to work as well.
+ for target_host in [host, "localhost"]:
+ print(f"Connecting to WebSocket via host {target_host}")
+ http = HTTPRequest(target_host, int(port))
+ with http.get("/json/version") as response:
+ data = json.loads(response.read())
+ assert session.capabilities["browserVersion"] in data["Browser"]
+
+ # Ensure Fission is not disabled (bug 1813981)
+ with using_context(session, "chrome"):
+ assert (
+ session.execute_script("""return Services.appinfo.fissionAutostart""")
+ is fission_enabled
+ )
diff --git a/testing/web-platform/mozilla/tests/webdriver/cdp/port_file.py b/testing/web-platform/mozilla/tests/webdriver/cdp/port_file.py
new file mode 100644
index 0000000000..aa294deb24
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/cdp/port_file.py
@@ -0,0 +1,30 @@
+import os
+
+from support.network import websocket_request
+
+
+def test_devtools_active_port_file(browser):
+ current_browser = browser(use_cdp=True)
+
+ assert current_browser.remote_agent_port != 0
+ assert current_browser.debugger_address.startswith("/devtools/browser/")
+
+ port_file = os.path.join(current_browser.profile.profile, "DevToolsActivePort")
+ assert os.path.exists(port_file)
+
+ current_browser.quit(clean_profile=False)
+ assert not os.path.exists(port_file)
+
+
+def test_connect(browser):
+ current_browser = browser(use_cdp=True)
+
+ # Both `localhost` and `127.0.0.1` have to accept connections.
+ for target_host in ["127.0.0.1", "localhost"]:
+ print(f"Connecting to the WebSocket via host {target_host}")
+ response = websocket_request(
+ target_host,
+ current_browser.remote_agent_port,
+ path=current_browser.debugger_address,
+ )
+ assert response.status == 101
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/scroll_into_view.py b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/scroll_into_view.py
new file mode 100644
index 0000000000..080195d345
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/scroll_into_view.py
@@ -0,0 +1,50 @@
+from tests.support.asserts import assert_success
+from tests.support.helpers import is_element_in_viewport
+
+
+def element_send_keys(session, element, text):
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/element/{element_id}/value".format(
+ session_id=session.session_id, element_id=element.id
+ ),
+ {"text": text},
+ )
+
+
+def test_option_select_container_outside_of_scrollable_viewport(session, inline):
+ session.url = inline(
+ """
+ <select style="margin-top: 102vh;">
+ <option value="foo">foo</option>
+ <option value="bar" id="bar">bar</option>
+ </select>
+ """
+ )
+ element = session.find.css("option#bar", all=False)
+ select = session.find.css("select", all=False)
+
+ response = element_send_keys(session, element, "bar")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, select)
+ assert is_element_in_viewport(session, element)
+
+
+def test_option_stays_outside_of_scrollable_viewport(session, inline):
+ session.url = inline(
+ """
+ <select multiple style="height: 105vh; margin-top: 100vh;">
+ <option value="foo" id="foo" style="height: 100vh;">foo</option>
+ <option value="bar" id="bar" style="background-color: yellow;">bar</option>
+ </select>
+ """
+ )
+ select = session.find.css("select", all=False)
+ option_bar = session.find.css("option#bar", all=False)
+
+ response = element_send_keys(session, option_bar, "bar")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, select)
+ assert is_element_in_viewport(session, option_bar)
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/send_keys.py b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/send_keys.py
new file mode 100644
index 0000000000..1399959ceb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/element_send_keys/send_keys.py
@@ -0,0 +1,24 @@
+from tests.support.asserts import assert_success
+from tests.support.keys import Keys
+
+
+def element_send_keys(session, element, text):
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/element/{element_id}/value".format(
+ session_id=session.session_id, element_id=element.id
+ ),
+ {"text": text},
+ )
+
+
+def test_modifier_key_toggles(session, inline, modifier_key):
+ session.url = inline("<input type=text value=foo>")
+ element = session.find.css("input", all=False)
+
+ response = element_send_keys(
+ session, element, f"{modifier_key}a{modifier_key}{Keys.DELETE}cheese"
+ )
+ assert_success(response)
+
+ assert element.property("value") == "cheese"
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/execute_async.py b/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/execute_async.py
new file mode 100644
index 0000000000..990f2c1b31
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/execute_async_script/execute_async.py
@@ -0,0 +1,59 @@
+import pytest
+from tests.support.asserts import assert_success
+from tests.support.sync import Poll
+
+
+def execute_async_script(session, script, args=None):
+ if args is None:
+ args = []
+ body = {"script": script, "args": args}
+
+ return session.transport.send(
+ "POST", "/session/{session_id}/execute/async".format(**vars(session)), body
+ )
+
+
+@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
+def test_no_abort_by_user_prompt_in_other_tab(session, inline, dialog_type):
+ original_handle = session.window_handle
+ original_handles = session.handles
+
+ session.url = inline(
+ """
+ <a onclick="window.open();">open window</a>
+ <script>
+ window.addEventListener("message", function (event) {{
+ {}("foo");
+ }});
+ </script>
+ """.format(
+ dialog_type
+ )
+ )
+
+ session.find.css("a", all=False).click()
+ wait = Poll(session, timeout=5, message="No new window has been opened")
+ new_handles = wait.until(lambda s: set(s.handles) - set(original_handles))
+ assert len(new_handles) == 1
+
+ session.window_handle = new_handles.pop()
+
+ response = execute_async_script(
+ session,
+ """
+ const resolve = arguments[0];
+
+ // Trigger opening a user prompt in the other window.
+ window.opener.postMessage("foo", "*");
+
+ // Delay resolving the Promise to ensure a user prompt has been opened.
+ setTimeout(() => resolve(42), 500);
+ """,
+ )
+
+ assert_success(response, 42)
+
+ session.window.close()
+
+ session.window_handle = original_handle
+ session.alert.accept()
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/chrome.py b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/chrome.py
new file mode 100644
index 0000000000..af24be4b9e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handle/chrome.py
@@ -0,0 +1,25 @@
+from support.context import using_context
+from tests.support.asserts import assert_success
+
+
+def get_window_handle(session):
+ return session.transport.send(
+ "GET", "session/{session_id}/window".format(**vars(session))
+ )
+
+
+def test_basic(session):
+ with using_context(session, "chrome"):
+ response = get_window_handle(session)
+ assert_success(response, session.window_handle)
+
+
+def test_different_handle_than_content_scope(session):
+ response = get_window_handle(session)
+ content_handle = assert_success(response)
+
+ with using_context(session, "chrome"):
+ response = get_window_handle(session)
+ chrome_handle = assert_success(response)
+
+ assert chrome_handle != content_handle
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/chrome.py b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/chrome.py
new file mode 100644
index 0000000000..091ac01e6c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/get_window_handles/chrome.py
@@ -0,0 +1,43 @@
+from support.context import using_context
+from tests.support.asserts import assert_success
+
+
+def get_window_handles(session):
+ return session.transport.send(
+ "GET", "session/{session_id}/window/handles".format(**vars(session))
+ )
+
+
+def test_basic(session):
+ with using_context(session, "chrome"):
+ response = get_window_handles(session)
+ assert_success(response, session.handles)
+
+
+def test_different_handles_than_content_scope(session):
+ response = get_window_handles(session)
+ content_handles = assert_success(response)
+
+ with using_context(session, "chrome"):
+ response = get_window_handles(session)
+ chrome_handles = assert_success(response)
+
+ assert chrome_handles != content_handles
+ assert len(chrome_handles) == 1
+ assert len(content_handles) == 1
+
+
+def test_multiple_windows_and_tabs(session):
+ session.new_window(type_hint="window")
+ session.new_window(type_hint="tab")
+
+ response = get_window_handles(session)
+ content_handles = assert_success(response)
+
+ with using_context(session, "chrome"):
+ response = get_window_handles(session)
+ chrome_handles = assert_success(response)
+
+ assert chrome_handles != content_handles
+ assert len(chrome_handles) == 2
+ assert len(content_handles) == 3
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/bidi_disabled.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/bidi_disabled.py
new file mode 100644
index 0000000000..eeb5a18740
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/bidi_disabled.py
@@ -0,0 +1,33 @@
+from copy import deepcopy
+
+
+def test_marionette_fallback_webdriver_session(configuration, geckodriver):
+ config = deepcopy(configuration)
+ config["capabilities"]["webSocketUrl"] = True
+
+ prefs = config["capabilities"]["moz:firefoxOptions"].get("prefs", {})
+ prefs.update({"remote.active-protocols": 2})
+ config["capabilities"]["moz:firefoxOptions"]["prefs"] = prefs
+
+ try:
+ driver = geckodriver(config=config)
+ driver.new_session()
+
+ assert driver.session.capabilities.get("webSocketUrl") is None
+
+ # Sanity check that Marionette works as expected and by default returns
+ # at least one window handle
+ assert len(driver.session.handles) >= 1
+
+ finally:
+ driver.stop()
+
+ # WebDriver BiDi has to be re-enabled. Because we cannot easily
+ # get rid of the value let geckodriver overwrite it with the current
+ # default.
+ prefs.update({"remote.active-protocols": 3})
+
+ driver = geckodriver(config=config)
+ driver.new_session()
+
+ assert driver.session.capabilities.get("webSocketUrl") is not None
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/binary.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/binary.py
new file mode 100644
index 0000000000..79d1f842ed
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/binary.py
@@ -0,0 +1,33 @@
+import os
+
+from tests.support.asserts import assert_error, assert_success
+
+
+def test_bad_binary(new_session, configuration):
+ # skipif annotations are forbidden in wpt
+ if os.path.exists("/bin/echo"):
+ capabilities = configuration["capabilities"].copy()
+ capabilities["moz:firefoxOptions"]["binary"] = "/bin/echo"
+
+ response, _ = new_session({"capabilities": {"alwaysMatch": capabilities}})
+ assert_error(response, "invalid argument")
+
+
+def test_shell_script_binary(new_session, configuration):
+ # skipif annotations are forbidden in wpt
+ if os.path.exists("/bin/bash"):
+ capabilities = configuration["capabilities"].copy()
+ binary = configuration["browser"]["binary"]
+
+ path = os.path.abspath("firefox.sh")
+ assert not os.path.exists(path)
+ try:
+ script = f"""#!/bin/bash\n\n"{binary}" $@\n"""
+ with open("firefox.sh", "w") as f:
+ f.write(script)
+ os.chmod(path, 0o744)
+ capabilities["moz:firefoxOptions"]["binary"] = path
+ response, _ = new_session({"capabilities": {"alwaysMatch": capabilities}})
+ assert_success(response)
+ finally:
+ os.unlink(path)
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/conftest.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/conftest.py
new file mode 100644
index 0000000000..1cab6784c2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/conftest.py
@@ -0,0 +1,58 @@
+import pytest
+from webdriver.transport import HTTPWireProtocol
+
+
+@pytest.fixture(name="configuration")
+def fixture_configuration(configuration):
+ """Remove "acceptInsecureCerts" from capabilities if it exists.
+
+ Some browser configurations add acceptInsecureCerts capability by default.
+ Remove it during new_session tests to avoid interference.
+ """
+ if "acceptInsecureCerts" in configuration["capabilities"]:
+ configuration = dict(configuration)
+ del configuration["capabilities"]["acceptInsecureCerts"]
+ return configuration
+
+
+@pytest.fixture(name="new_session")
+def fixture_new_session(request, configuration, current_session):
+ """Start a new session for tests which themselves test creating new sessions.
+
+ :param body: The content of the body for the new session POST request.
+
+ :param delete_existing_session: Allows the fixture to delete an already
+ created custom session before the new session is getting created. This
+ is useful for tests which call this fixture multiple times within the
+ same test.
+ """
+ custom_session = {}
+
+ transport = HTTPWireProtocol(
+ configuration["host"],
+ configuration["port"],
+ url_prefix="/",
+ )
+
+ def _delete_session(session_id):
+ transport.send("DELETE", "session/{}".format(session_id))
+
+ def new_session(body, delete_existing_session=False, headers=None):
+ # If there is an active session from the global session fixture,
+ # delete that one first
+ if current_session is not None:
+ current_session.end()
+
+ if delete_existing_session:
+ _delete_session(custom_session["session"]["sessionId"])
+
+ response = transport.send("POST", "session", body, headers=headers)
+ if response.status == 200:
+ custom_session["session"] = response.body["value"]
+ return response, custom_session.get("session", None)
+
+ yield new_session
+
+ if custom_session.get("session") is not None:
+ _delete_session(custom_session["session"]["sessionId"])
+ custom_session = None
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/create.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/create.py
new file mode 100644
index 0000000000..9649b938ad
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/create.py
@@ -0,0 +1,11 @@
+# META: timeout=long
+from tests.support.asserts import assert_success
+
+
+def test_valid_content_type(new_session, configuration):
+ headers = {"content-type": "application/json"}
+ response, _ = new_session(
+ {"capabilities": {"alwaysMatch": dict(configuration["capabilities"])}},
+ headers=headers,
+ )
+ assert_success(response)
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/invalid.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/invalid.py
new file mode 100644
index 0000000000..dc7a0caee9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/invalid.py
@@ -0,0 +1,53 @@
+from copy import deepcopy
+
+import pytest
+from tests.support.asserts import assert_error
+
+
+@pytest.mark.parametrize(
+ "headers",
+ [
+ {"origin": "http://localhost"},
+ {"origin": "http://localhost:8000"},
+ {"origin": "http://127.0.0.1"},
+ {"origin": "http://127.0.0.1:8000"},
+ {"origin": "null"},
+ {"ORIGIN": "https://example.org"},
+ {"host": "example.org:4444"},
+ {"Host": "example.org"},
+ {"host": "localhost:80"},
+ {"host": "localhost"},
+ {"content-type": "application/x-www-form-urlencoded"},
+ {"content-type": "multipart/form-data"},
+ {"content-type": "text/plain"},
+ {"Content-TYPE": "APPLICATION/x-www-form-urlencoded"},
+ {"content-type": "MULTIPART/FORM-DATA"},
+ {"CONTENT-TYPE": "TEXT/PLAIN"},
+ {"content-type": "text/plain ; charset=utf-8"},
+ {"content-type": "text/plain;foo"},
+ {"content-type": "text/PLAIN ; foo;charset=utf8"},
+ ],
+)
+def test_invalid(new_session, configuration, headers):
+ response, _ = new_session(
+ {"capabilities": {"alwaysMatch": dict(configuration["capabilities"])}},
+ headers=headers,
+ )
+ assert_error(response, "unknown error")
+
+
+@pytest.mark.parametrize(
+ "argument",
+ [
+ "--marionette",
+ "--remote-debugging-port",
+ "--remote-allow-hosts",
+ "--remote-allow-origins",
+ ],
+)
+def test_forbidden_arguments(configuration, new_session, argument):
+ capabilities = deepcopy(configuration["capabilities"])
+ capabilities["moz:firefoxOptions"]["args"] = [argument]
+
+ response, _ = new_session({"capabilities": {"alwaysMatch": capabilities}})
+ assert_error(response, "invalid argument")
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/new_session/profile_root.py b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/profile_root.py
new file mode 100644
index 0000000000..8bbdbadc69
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/new_session/profile_root.py
@@ -0,0 +1,38 @@
+import copy
+import os
+
+import pytest
+
+
+def test_profile_root(tmp_path, configuration, geckodriver):
+ profile_path = os.path.join(tmp_path, "geckodriver-test")
+ os.makedirs(profile_path)
+
+ config = copy.deepcopy(configuration)
+ # Ensure we don't set a profile in command line arguments
+ del config["capabilities"]["moz:firefoxOptions"]["args"]
+
+ extra_args = ["--profile-root", profile_path]
+
+ assert os.listdir(profile_path) == []
+
+ driver = geckodriver(config=config, extra_args=extra_args)
+ driver.new_session()
+ assert len(os.listdir(profile_path)) == 1
+ driver.delete_session()
+ assert os.listdir(profile_path) == []
+
+
+def test_profile_root_missing(tmp_path, configuration, geckodriver):
+ profile_path = os.path.join(tmp_path, "missing-path")
+ assert not os.path.exists(profile_path)
+
+ config = copy.deepcopy(configuration)
+ # Ensure we don't set a profile in command line arguments
+ del config["capabilities"]["moz:firefoxOptions"]["args"]
+
+ extra_args = ["--profile-root", profile_path]
+
+ with pytest.raises(ChildProcessError) as exc_info:
+ geckodriver(config=config, extra_args=extra_args)
+ assert str(exc_info.value) == "geckodriver terminated with code 64"
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/protocol/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_hosts.py b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_hosts.py
new file mode 100644
index 0000000000..17ae2c2c68
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_hosts.py
@@ -0,0 +1,53 @@
+from copy import deepcopy
+
+import pytest
+from support.network import get_host, http_request, websocket_request
+
+
+@pytest.mark.parametrize(
+ "allow_hosts, hostname, port_type, status",
+ [
+ # Valid hosts
+ (["localhost.localdomain", "localhost"], "localhost", "server_port", 200),
+ (["localhost.localdomain", "localhost"], "127.0.0.1", "server_port", 200),
+ # Invalid hosts
+ (["localhost.localdomain"], "localhost", "server_port", 500),
+ (["localhost"], "localhost", "wrong_port", 500),
+ (["www.localhost"], "localhost", "server_port", 500),
+ ],
+)
+def test_allow_hosts(geckodriver, allow_hosts, hostname, port_type, status):
+ extra_args = ["--allow-hosts"] + allow_hosts
+
+ driver = geckodriver(hostname=hostname, extra_args=extra_args)
+ host = get_host(port_type, hostname, driver.port)
+ response = http_request(driver.hostname, driver.port, host=host)
+
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "allow_hosts, hostname, status",
+ [
+ (["mozilla.org", "testhost"], "testhost", 101),
+ (["mozilla.org"], "testhost", 400),
+ ],
+ ids=["allowed", "not allowed"],
+)
+def test_allow_hosts_passed_to_remote_agent(
+ configuration, geckodriver, allow_hosts, hostname, status
+):
+ config = deepcopy(configuration)
+ config["capabilities"]["webSocketUrl"] = True
+
+ extra_args = ["--allow-hosts"] + allow_hosts
+
+ driver = geckodriver(config=config, extra_args=extra_args)
+
+ driver.new_session()
+
+ host = get_host("default_port", hostname, driver.remote_agent_port)
+ response = websocket_request("127.0.0.1", driver.remote_agent_port, host=host)
+ assert response.status == status
+
+ driver.delete_session()
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_origins.py b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_origins.py
new file mode 100644
index 0000000000..72b6fba482
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/allow_origins.py
@@ -0,0 +1,56 @@
+from copy import deepcopy
+
+import pytest
+from support.network import http_request, websocket_request
+
+
+@pytest.mark.parametrize(
+ "allow_origins, origin, status",
+ [
+ # Valid origins
+ (["http://web-platform.test"], "http://web-platform.test", 200),
+ (["http://web-platform.test"], "http://web-platform.test:80", 200),
+ (["https://web-platform.test"], "https://web-platform.test:443", 200),
+ # Invalid origins
+ (["https://web-platform.test"], "http://web-platform.test", 500),
+ (["http://web-platform.test:8000"], "http://web-platform.test", 500),
+ (["http://web-platform.test"], "http://www.web-platform.test", 500),
+ ],
+)
+def test_allow_hosts(configuration, geckodriver, allow_origins, origin, status):
+ extra_args = ["--allow-origins"] + allow_origins
+
+ driver = geckodriver(extra_args=extra_args)
+ response = http_request(driver.hostname, driver.port, origin=origin)
+
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "allow_origins, origin, status",
+ [
+ (
+ ["https://web-platform.test", "http://web-platform.test"],
+ "http://web-platform.test",
+ 101,
+ ),
+ (["https://web-platform.test"], "http://web-platform.test", 400),
+ ],
+ ids=["allowed", "not allowed"],
+)
+def test_allow_origins_passed_to_remote_agent(
+ configuration, geckodriver, allow_origins, origin, status
+):
+ config = deepcopy(configuration)
+ config["capabilities"]["webSocketUrl"] = True
+
+ extra_args = ["--allow-origins"] + allow_origins
+
+ driver = geckodriver(config=config, extra_args=extra_args)
+
+ driver.new_session()
+
+ response = websocket_request("127.0.0.1", driver.remote_agent_port, origin=origin)
+ assert response.status == status
+
+ driver.delete_session()
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/protocol/marionette_port.py b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/marionette_port.py
new file mode 100644
index 0000000000..09951abc43
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/marionette_port.py
@@ -0,0 +1,41 @@
+import os
+from copy import deepcopy
+
+import pytest
+
+
+@pytest.mark.parametrize("port", ["0", "2828"], ids=["system allocated", "fixed"])
+def test_marionette_port(geckodriver, port):
+ extra_args = ["--marionette-port", port]
+
+ driver = geckodriver(extra_args=extra_args)
+ driver.new_session()
+ driver.delete_session()
+
+
+def test_marionette_port_outdated_active_port_file(
+ configuration, geckodriver, custom_profile
+):
+ config = deepcopy(configuration)
+ extra_args = ["--marionette-port", "0"]
+
+ # Prepare a Marionette active port file that contains a port which will
+ # never be used when requesting a system allocated port.
+ active_port_file = os.path.join(custom_profile.profile, "MarionetteActivePort")
+ with open(active_port_file, "wb") as f:
+ f.write(b"53")
+
+ config["capabilities"]["moz:firefoxOptions"]["args"] = [
+ "--profile",
+ custom_profile.profile,
+ ]
+
+ driver = geckodriver(config=config, extra_args=extra_args)
+
+ driver.new_session()
+ with open(active_port_file, "rb") as f:
+ assert f.readline() != b"53"
+
+ driver.delete_session()
+ with pytest.raises(FileNotFoundError):
+ open(active_port_file, "rb")
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/protocol/request.py b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/request.py
new file mode 100644
index 0000000000..ad99d6964d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/protocol/request.py
@@ -0,0 +1,72 @@
+import pytest
+from support.network import get_host, http_request
+
+
+@pytest.mark.parametrize(
+ "hostname, port_type, status",
+ [
+ # Valid hosts
+ ("localhost", "server_port", 200),
+ ("127.0.0.1", "server_port", 200),
+ ("[::1]", "server_port", 200),
+ ("192.168.8.1", "server_port", 200),
+ ("[fdf8:f535:82e4::53]", "server_port", 200),
+ # Invalid hosts
+ ("localhost", "default_port", 500),
+ ("127.0.0.1", "default_port", 500),
+ ("[::1]", "default_port", 500),
+ ("192.168.8.1", "default_port", 500),
+ ("[fdf8:f535:82e4::53]", "default_port", 500),
+ ("example.org", "server_port", 500),
+ ("example.org", "wrong_port", 500),
+ ("example.org", "default_port", 500),
+ ("localhost", "wrong_port", 500),
+ ("127.0.0.1", "wrong_port", 500),
+ ("[::1]", "wrong_port", 500),
+ ("192.168.8.1", "wrong_port", 500),
+ ("[fdf8:f535:82e4::53]", "wrong_port", 500),
+ ],
+ ids=[
+ # Valid hosts
+ "localhost with same port as server",
+ "127.0.0.1 (loopback) with same port as server",
+ "[::1] (ipv6 loopback) with same port as server",
+ "ipv4 address with same port as server",
+ "ipv6 address with same port as server",
+ # Invalid hosts
+ "localhost with default port",
+ "127.0.0.1 (loopback) with default port",
+ "[::1] (ipv6 loopback) with default port",
+ "ipv4 address with default port",
+ "ipv6 address with default port",
+ "random hostname with the same port as server",
+ "random hostname with a different port than server",
+ "random hostname with default port",
+ "localhost with a different port than server",
+ "127.0.0.1 (loopback) with a different port than server",
+ "[::1] (ipv6 loopback) with a different port than server",
+ "ipv4 address with a different port than server",
+ "ipv6 address with a different port than server",
+ ],
+)
+def test_host_header(configuration, hostname, port_type, status):
+ host = get_host(port_type, hostname, configuration["port"])
+ response = http_request(configuration["host"], configuration["port"], host=host)
+
+ assert response.status == status
+
+
+@pytest.mark.parametrize(
+ "origin, add_port, status",
+ [
+ (None, False, 200),
+ ("", False, 500),
+ ("sometext", False, 500),
+ ("http://localhost", True, 500),
+ ],
+)
+def test_origin_header(configuration, origin, add_port, status):
+ if add_port:
+ origin = f"{origin}:{configuration['port']}"
+ response = http_request(configuration["host"], configuration["port"], origin=origin)
+ assert response.status == status
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/send_alert_text.py b/testing/web-platform/mozilla/tests/webdriver/classic/send_alert_text.py
new file mode 100644
index 0000000000..60d6a02af0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/send_alert_text.py
@@ -0,0 +1,22 @@
+from tests.support.asserts import assert_error
+from tests.support.http_handlers.authentication import basic_authentication
+
+
+def send_alert_text(session, text=None):
+ return session.transport.send(
+ "POST",
+ "session/{session_id}/alert/text".format(**vars(session)),
+ {"text": text},
+ )
+
+
+def test_basic_auth_unsupported_operation(url, session):
+ """
+ Basic auth dialogues are not included in HTML's definition of
+ 'user prompts': those are limited to the 'simple dialogues'
+ such as window.alert(), window.prompt() et al. and the print
+ dialogue.
+ """
+ session.url = basic_authentication(url)
+ response = send_alert_text(session, "Federer")
+ assert_error(response, "unsupported operation")
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/__init__.py b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/__init__.py
new file mode 100644
index 0000000000..11a8a58a0f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/__init__.py
@@ -0,0 +1,12 @@
+def document_dimensions(session):
+ return tuple(
+ session.execute_script(
+ """
+ const {devicePixelRatio} = window;
+ const width = document.documentElement.scrollWidth;
+ const height = document.documentElement.scrollHeight;
+
+ return [Math.floor(width * devicePixelRatio), Math.floor(height * devicePixelRatio)];
+ """
+ )
+ )
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/iframe.py b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/iframe.py
new file mode 100644
index 0000000000..fc231f2e11
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/iframe.py
@@ -0,0 +1,47 @@
+import pytest
+from tests.support.asserts import assert_success
+from tests.support.image import png_dimensions
+
+from . import document_dimensions
+
+DEFAULT_CSS_STYLE = """
+ <style>
+ div, iframe {
+ display: block;
+ border: 1px solid blue;
+ width: 10em;
+ height: 10em;
+ }
+ </style>
+"""
+
+DEFAULT_CONTENT = "<div>Lorem ipsum dolor sit amet.</div>"
+
+
+def take_full_screenshot(session):
+ return session.transport.send(
+ "GET",
+ "/session/{session_id}/moz/screenshot/full".format(
+ session_id=session.session_id
+ ),
+ )
+
+
+@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
+def test_source_origin(session, url, domain, inline, iframe):
+ session.url = inline("""{0}{1}""".format(DEFAULT_CSS_STYLE, DEFAULT_CONTENT))
+
+ response = take_full_screenshot(session)
+ reference_screenshot = assert_success(response)
+ assert png_dimensions(reference_screenshot) == document_dimensions(session)
+
+ iframe_content = "<style>body {{ margin: 0; }}</style>{}".format(DEFAULT_CONTENT)
+ session.url = inline(
+ """{0}{1}""".format(DEFAULT_CSS_STYLE, iframe(iframe_content, domain=domain))
+ )
+
+ response = take_full_screenshot(session)
+ screenshot = assert_success(response)
+ assert png_dimensions(screenshot) == document_dimensions(session)
+
+ assert screenshot == reference_screenshot
diff --git a/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/screenshot.py b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/screenshot.py
new file mode 100644
index 0000000000..02373afd57
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/classic/take_full_screenshot/screenshot.py
@@ -0,0 +1,51 @@
+from tests.support.asserts import assert_error, assert_png, assert_success
+from tests.support.image import png_dimensions
+
+from . import document_dimensions
+
+
+def take_full_screenshot(session):
+ return session.transport.send(
+ "GET",
+ "/session/{session_id}/moz/screenshot/full".format(
+ session_id=session.session_id
+ ),
+ )
+
+
+def test_no_browsing_context(session, closed_window):
+ response = take_full_screenshot(session)
+ assert_error(response, "no such window")
+
+
+def test_html_document(session, inline):
+ session.url = inline("<input>")
+
+ response = take_full_screenshot(session)
+ value = assert_success(response)
+ assert_png(value)
+ assert png_dimensions(value) == document_dimensions(session)
+
+
+def test_xhtml_document(session, inline):
+ session.url = inline('<input type="text" />', doctype="xhtml")
+
+ response = take_full_screenshot(session)
+ value = assert_success(response)
+ assert_png(value)
+ assert png_dimensions(value) == document_dimensions(session)
+
+
+def test_document_extends_beyond_viewport(session, inline):
+ session.url = inline(
+ """
+ <style>
+ body { min-height: 200vh }
+ </style>
+ """
+ )
+
+ response = take_full_screenshot(session)
+ value = assert_success(response)
+ assert_png(value)
+ assert png_dimensions(value) == document_dimensions(session)
diff --git a/testing/web-platform/mozilla/tests/webdriver/conftest.py b/testing/web-platform/mozilla/tests/webdriver/conftest.py
new file mode 100644
index 0000000000..d754b39e79
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/conftest.py
@@ -0,0 +1,15 @@
+import os
+import sys
+
+base = os.path.dirname(__file__)
+webdriver_path = os.path.abspath(
+ os.path.join(base, "..", "..", "..", "tests", "webdriver")
+)
+sys.path.insert(0, os.path.join(webdriver_path))
+
+pytest_plugins = [
+ "support.fixtures",
+ "tests.support.fixtures",
+ "tests.support.fixtures_bidi",
+ "tests.support.fixtures_http",
+]
diff --git a/testing/web-platform/mozilla/tests/webdriver/support/__init__.py b/testing/web-platform/mozilla/tests/webdriver/support/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/support/__init__.py
diff --git a/testing/web-platform/mozilla/tests/webdriver/support/context.py b/testing/web-platform/mozilla/tests/webdriver/support/context.py
new file mode 100644
index 0000000000..910b202075
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/support/context.py
@@ -0,0 +1,20 @@
+import contextlib
+
+
+def set_context(session, context):
+ session.send_session_command("POST", "moz/context", {"context": context})
+
+
+@contextlib.contextmanager
+def using_context(session, context):
+ orig_context = session.send_session_command("GET", "moz/context")
+ needs_change = context != orig_context
+
+ if needs_change:
+ set_context(session, context)
+
+ try:
+ yield
+ finally:
+ if needs_change:
+ set_context(session, orig_context)
diff --git a/testing/web-platform/mozilla/tests/webdriver/support/fixtures.py b/testing/web-platform/mozilla/tests/webdriver/support/fixtures.py
new file mode 100644
index 0000000000..450f662969
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/support/fixtures.py
@@ -0,0 +1,256 @@
+import json
+import os
+import socket
+import subprocess
+import time
+from contextlib import suppress
+from urllib.parse import urlparse
+
+import pytest
+import webdriver
+from mozprofile import Profile
+from mozrunner import FirefoxRunner
+
+from support.network import get_free_port
+
+
+@pytest.fixture(scope="module")
+def browser(full_configuration):
+ """Start a Firefox instance without using geckodriver.
+
+ geckodriver will automatically use the --remote-allow-hosts and
+ --remote.allow.origins command line arguments.
+
+ Starting Firefox without geckodriver allows to set those command line arguments
+ as needed. The fixture method returns the browser instance that should be used
+ to connect to a RemoteAgent supported protocol (CDP, WebDriver BiDi).
+ """
+ current_browser = None
+
+ def _browser(use_bidi=False, use_cdp=False, extra_args=None, extra_prefs=None):
+ nonlocal current_browser
+
+ # If the requested preferences and arguments match the ones for the
+ # already started firefox, we can reuse the current firefox instance,
+ # return the instance immediately.
+ if current_browser:
+ if (
+ current_browser.use_bidi == use_bidi
+ and current_browser.use_cdp == use_cdp
+ and current_browser.extra_args == extra_args
+ and current_browser.extra_prefs == extra_prefs
+ and current_browser.is_running
+ ):
+ return current_browser
+
+ # Otherwise, if firefox is already started, terminate it because we need
+ # to create a new instance for the provided preferences.
+ current_browser.quit()
+
+ binary = full_configuration["browser"]["binary"]
+ firefox_options = full_configuration["capabilities"]["moz:firefoxOptions"]
+ current_browser = Browser(
+ binary,
+ firefox_options,
+ use_bidi=use_bidi,
+ use_cdp=use_cdp,
+ extra_args=extra_args,
+ extra_prefs=extra_prefs,
+ )
+ current_browser.start()
+ return current_browser
+
+ yield _browser
+
+ # Stop firefox at the end of the test module.
+ if current_browser is not None:
+ current_browser.quit()
+ current_browser = None
+
+
+@pytest.fixture
+def custom_profile(configuration):
+ # Clone the known profile for automation preferences
+ firefox_options = configuration["capabilities"]["moz:firefoxOptions"]
+ _, profile_folder = firefox_options["args"]
+ profile = Profile.clone(profile_folder)
+
+ yield profile
+
+ profile.cleanup()
+
+
+@pytest.fixture
+def geckodriver(configuration):
+ """Start a geckodriver instance directly."""
+ driver = None
+
+ def _geckodriver(config=None, hostname=None, extra_args=None):
+ nonlocal driver
+
+ if config is None:
+ config = configuration
+
+ driver = Geckodriver(config, hostname, extra_args)
+ driver.start()
+
+ return driver
+
+ yield _geckodriver
+
+ if driver is not None:
+ driver.stop()
+
+
+class Browser:
+ def __init__(
+ self,
+ binary,
+ firefox_options,
+ use_bidi=False,
+ use_cdp=False,
+ extra_args=None,
+ extra_prefs=None,
+ ):
+ self.use_bidi = use_bidi
+ self.bidi_port_file = None
+ self.use_cdp = use_cdp
+ self.cdp_port_file = None
+ self.extra_args = extra_args
+ self.extra_prefs = extra_prefs
+
+ self.debugger_address = None
+ self.remote_agent_host = None
+ self.remote_agent_port = None
+
+ # Prepare temporary profile
+ _profile_arg, profile_folder = firefox_options["args"]
+ self.profile = Profile.clone(profile_folder)
+ if self.extra_prefs is not None:
+ self.profile.set_preferences(self.extra_prefs)
+
+ if use_cdp:
+ self.cdp_port_file = os.path.join(
+ self.profile.profile, "DevToolsActivePort"
+ )
+ with suppress(FileNotFoundError):
+ os.remove(self.cdp_port_file)
+ if use_bidi:
+ self.webdriver_bidi_file = os.path.join(
+ self.profile.profile, "WebDriverBiDiServer.json"
+ )
+ with suppress(FileNotFoundError):
+ os.remove(self.webdriver_bidi_file)
+
+ cmdargs = ["-no-remote"]
+ if self.use_bidi or self.use_cdp:
+ cmdargs.extend(["--remote-debugging-port", "0"])
+ if self.extra_args is not None:
+ cmdargs.extend(self.extra_args)
+ self.runner = FirefoxRunner(
+ binary=binary, profile=self.profile, cmdargs=cmdargs
+ )
+
+ @property
+ def is_running(self):
+ return self.runner.is_running()
+
+ def start(self):
+ # Start Firefox.
+ self.runner.start()
+
+ if self.use_bidi:
+ # Wait until the WebDriverBiDiServer.json file is ready
+ while not os.path.exists(self.webdriver_bidi_file):
+ time.sleep(0.1)
+
+ # Read the connection details from file
+ data = json.loads(open(self.webdriver_bidi_file).read())
+ self.remote_agent_host = data["ws_host"]
+ self.remote_agent_port = int(data["ws_port"])
+
+ if self.use_cdp:
+ # Wait until the DevToolsActivePort file is ready
+ while not os.path.exists(self.cdp_port_file):
+ time.sleep(0.1)
+
+ # Read the port if needed and the debugger address from the
+ # DevToolsActivePort file
+ lines = open(self.cdp_port_file).readlines()
+ assert len(lines) == 2
+
+ if self.remote_agent_port is None:
+ self.remote_agent_port = int(lines[0].strip())
+ self.debugger_address = lines[1].strip()
+
+ def quit(self, clean_profile=True):
+ if self.is_running:
+ self.runner.stop()
+ self.runner.cleanup()
+
+ if clean_profile:
+ self.profile.cleanup()
+
+
+class Geckodriver:
+ def __init__(self, configuration, hostname=None, extra_args=None):
+ self.config = configuration["webdriver"]
+ self.requested_capabilities = configuration["capabilities"]
+ self.hostname = hostname or configuration["host"]
+ self.extra_args = extra_args or []
+
+ self.command = None
+ self.proc = None
+ self.port = get_free_port()
+
+ capabilities = {"alwaysMatch": self.requested_capabilities}
+ self.session = webdriver.Session(
+ self.hostname, self.port, capabilities=capabilities
+ )
+
+ @property
+ def remote_agent_port(self):
+ webSocketUrl = self.session.capabilities.get("webSocketUrl")
+ assert webSocketUrl is not None
+
+ return urlparse(webSocketUrl).port
+
+ def start(self):
+ self.command = (
+ [self.config["binary"], "--port", str(self.port)]
+ + self.config["args"]
+ + self.extra_args
+ )
+
+ print(f"Running command: {' '.join(self.command)}")
+ self.proc = subprocess.Popen(self.command)
+
+ # Wait for the port to become ready
+ end_time = time.time() + 10
+ while time.time() < end_time:
+ returncode = self.proc.poll()
+ if returncode is not None:
+ raise ChildProcessError(
+ f"geckodriver terminated with code {returncode}"
+ )
+ with socket.socket() as sock:
+ if sock.connect_ex((self.hostname, self.port)) == 0:
+ break
+ else:
+ raise ConnectionRefusedError(
+ f"Failed to connect to geckodriver on {self.hostname}:{self.port}"
+ )
+
+ return self
+
+ def stop(self):
+ self.delete_session()
+
+ if self.proc:
+ self.proc.kill()
+
+ def new_session(self):
+ self.session.start()
+
+ def delete_session(self):
+ self.session.end()
diff --git a/testing/web-platform/mozilla/tests/webdriver/support/network.py b/testing/web-platform/mozilla/tests/webdriver/support/network.py
new file mode 100644
index 0000000000..25492ca5e5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webdriver/support/network.py
@@ -0,0 +1,78 @@
+import socket
+from http.client import HTTPConnection
+
+
+def websocket_request(
+ remote_agent_host, remote_agent_port, host=None, origin=None, path="/session"
+):
+ real_host = f"{remote_agent_host}:{remote_agent_port}"
+ url = f"http://{real_host}{path}"
+
+ conn = HTTPConnection(real_host)
+
+ skip_host = host is not None
+ conn.putrequest("GET", url, skip_host)
+
+ if host is not None:
+ conn.putheader("Host", host)
+
+ if origin is not None:
+ conn.putheader("Origin", origin)
+
+ conn.putheader("Connection", "upgrade")
+ conn.putheader("Upgrade", "websocket")
+ conn.putheader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
+ conn.putheader("Sec-WebSocket-Version", "13")
+
+ conn.endheaders()
+
+ return conn.getresponse()
+
+
+def http_request(server_host, server_port, path="/status", host=None, origin=None):
+ url = f"http://{server_host}:{server_port}{path}"
+
+ conn = HTTPConnection(server_host, server_port)
+
+ custom_host = host is not None
+ conn.putrequest("GET", url, skip_host=custom_host)
+ if custom_host:
+ conn.putheader("Host", host)
+
+ if origin is not None:
+ conn.putheader("Origin", origin)
+
+ conn.endheaders()
+
+ return conn.getresponse()
+
+
+def get_free_port():
+ """Get a random unbound port"""
+ max_attempts = 10
+ err = None
+ for _ in range(max_attempts):
+ s = socket.socket()
+ try:
+ s.bind(("127.0.0.1", 0))
+ except OSError as e:
+ err = e
+ continue
+ else:
+ return s.getsockname()[1]
+ finally:
+ s.close()
+ if err is None:
+ err = Exception("Failed to get a free port")
+ raise err
+
+
+def get_host(port_type, hostname, server_port):
+ if port_type == "default_port":
+ return hostname
+ if port_type == "server_port":
+ return f"{hostname}:{server_port}"
+ if port_type == "wrong_port":
+ wrong_port = int(server_port) + 1
+ return f"{hostname}:{wrong_port}"
+ raise Exception(f"Unrecognised port_type {port_type}")
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/1/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/1/cts.https.html
new file mode 100644
index 0000000000..a651e43371
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/1/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestAdapter:requestAdapter:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestAdapter:requestAdapter_no_parameters:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestAdapterInfo:adapter_info:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestAdapterInfo:adapter_info_with_hints:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:default:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:invalid:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:features,unknown:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:features,known:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:limits,unknown:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:limits,supported:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:limit,better_than_supported:*'>
+<meta name=variant content='?q=webgpu:api,operation,adapter,requestDevice:limit,worse_than_default:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,write:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,write,unchanged_ranges_preserved:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,read:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,read,typedArrayAccess:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mapAsync,mapState:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:mappedAtCreation,mapState:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map:remapped_for_write:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map_ArrayBuffer:postMessage:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map_detach:while_mapped:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:mapAsync:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,operation,buffers,threading:serialize:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/10/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/10/cts.https.html
new file mode 100644
index 0000000000..bb938734b0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/10/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,invalid_mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappedAgain:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,unmapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,destroyed:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,state,mappingPending:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,subrange,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,offsetAndSizeAlignment,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,sizeAndOffsetOOB,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjointRanges:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,disjoinRanges_many:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,unmapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,destroyed:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,state,mappingPending:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:gc_behavior,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:gc_behavior,mapAsync:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,query_types:createQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,query_types:writeTimestamp:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_descriptor:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/11/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/11/cts.https.html
new file mode 100644
index 0000000000..7e0ba911d2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/11/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_descriptor_view_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:texture_view_descriptor:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:canvas_configuration:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:canvas_configuration_view_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:depth_stencil_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,capability_checks,features,texture_formats:render_bundle_encoder_descriptor_depth_stencil_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:basic:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:shader_module,invalid:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:shader_module,compute:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:shader_module,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:pipeline_layout,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:limits,workgroup_storage_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:limits,invocations_per_workgroup:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:limits,invocations_per_workgroup,each_component:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,identifier:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,uninitialized:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,value,type_error:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,value,validation_error:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,value,validation_error,f16:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits:*'>
+<meta name=variant content='?q=webgpu:api,validation,compute_pipeline:overrides,workgroup_size,limits,workgroup_storage_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_count_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_must_be_present_in_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_must_contain_resource_defined_in_layout:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/12/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/12/cts.https.html
new file mode 100644
index 0000000000..b5a0044f96
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/12/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_component_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture_must_have_correct_dimension:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:multisampled_validation:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer_offset_and_size_for_bind_groups_match:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:minBindingSize:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,resource_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,resource_offset:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,resource_binding_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:buffer,effective_buffer_binding_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:texture,resource_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:bind_group_layout,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_resources,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:storage_texture,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:storage_texture,mip_level_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:storage_texture,format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:sampler,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroup:sampler,compare_function_with_binding_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:duplicate_bindings:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:maximum_binding_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:visibility:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:visibility,VERTEX_shader_stage_buffer_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:visibility,VERTEX_shader_stage_storage_texture_access:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:multisampled_validation:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/13/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/13/cts.https.html
new file mode 100644
index 0000000000..defa0b68a6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/13/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_dynamic_buffers:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_bind_group_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_pipeline_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:storage_texture,layout_dimension:*'>
+<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:storage_texture,formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:number_of_dynamic_buffers_exceeds_the_maximum_value:*'>
+<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:number_of_bind_group_layouts_exceeds_the_maximum_value:*'>
+<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:bind_group_layouts,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,createSampler:lodMinAndMaxClamp:*'>
+<meta name=variant content='?q=webgpu:api,validation,createSampler:maxAnisotropy:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:zero_size_and_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:dimension_type_and_format_compatibility:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:mipLevelCount,bound_check,bigger_than_integer_bit_width:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,various_sampleCount_with_all_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:sampleCount,valid_sampleCount_with_other_parameter_varies:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:sample_count,1d_2d_array_3d:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,default_value_and_smallest_size,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,1d_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,2d_texture,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,2d_texture,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,3d_texture,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_size,3d_texture,compressed_format:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/14/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/14/cts.https.html
new file mode 100644
index 0000000000..8b785ba326
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/14/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,createTexture:texture_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,createTexture:viewFormats:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:format:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:dimension:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:aspect:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:array_layers:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:mip_levels:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:cube_faces_square:*'>
+<meta name=variant content='?q=webgpu:api,validation,createView:texture_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,debugMarker:push_pop_call_count_unbalance,command_encoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,debugMarker:push_pop_call_count_unbalance,render_compute_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,same_location:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,query_set_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,invalid_query_set:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginComputePass:timestampWrites,query_index_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginComputePass:timestamp_query_set,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:color_attachments,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:depth_stencil_attachment,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:occlusion_query_set,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,beginRenderPass:timestamp_query_set,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:default_args:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:buffer_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:size_alignment:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/15/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/15/cts.https.html
new file mode 100644
index 0000000000..9daf585acb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/15/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:overflow:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,clearBuffer:out_of_bounds:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:set_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:pipeline,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:dispatch_sizes:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,compute_pass:indirect_dispatch_buffer,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:buffer_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_size_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_overflow:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_out_of_bounds:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyBufferToBuffer:copy_within_same_buffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_with_invalid_or_destroyed_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:mipmap_level:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:multisampled_copy_restrictions:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:texture_format_compatibility:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:depth_stencil_copy_restrictions:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/16/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/16/cts.https.html
new file mode 100644
index 0000000000..81ca6c2d5e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/16/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_within_same_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_aspects:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_group_balanced:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,debug:debug_marker:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,index_access:out_of_bounds_zero_sized_index_buffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:unused_buffer_bound:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:index_buffer_OOB:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:vertex_buffer_OOB:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:buffer_binding_overlap:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:last_buffer_setting_take_account:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,draw:max_draw_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,x_y_width_height_nonnegative:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,xy_rect_contained_in_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setViewport,depth_rangeAndOrder:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,x_y_width_height_nonnegative:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setScissorRect,xy_rect_contained_in_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setBlendConstant:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,dynamic_state:setStencilReference:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_buffer_usage:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/17/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/17/cts.https.html
new file mode 100644
index 0000000000..2839312856
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/17/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,indirect_draw:indirect_offset_oob:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setIndexBuffer:offset_and_size_oob:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setPipeline:invalid_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setPipeline:pipeline,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:slot:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,setVertexBuffer:offset_and_size_oob:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_vertex_buffer_should_be_bound:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:all_needed_index_buffer_should_be_bound:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_inherit_from_previous_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,render,state_tracking:vertex_buffers_do_not_inherit_between_render_passes:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:state_and_binding_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:bind_group,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_passed_but_not_expected:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:dynamic_offsets_match_expectations_in_pass_encoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:u32array_start_and_length:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,cmds,setBindGroup:buffer_dynamic_offsets:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/18/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/18/cts.https.html
new file mode 100644
index 0000000000..0b87d0004a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/18/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachments:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachmentBytesPerSample,aligned:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,limits,maxColorAttachmentBytesPerSample,unaligned:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:attachment_state,empty_color_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:valid_texture_formats:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,createRenderBundleEncoder:depth_stencil_readonly_with_undefined_depth:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_open_state:non_pass_commands:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_open_state:render_pass_commands:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_open_state:render_bundle_commands:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_open_state:compute_pass_commands:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_state:pass_end_invalid_order:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_state:call_after_successful_finish:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_state:pass_end_none:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,encoder_state:pass_end_twice:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bind_groups_and_pipeline_layout_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:buffer_binding,render_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:sampler_binding,render_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_binding_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_visibility_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:bgl_resource_type_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,compute_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,programmable,pipeline_bind_group_compat:empty_bind_group_layouts_requires_empty_bind_groups,render_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_balance:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,begin_end_invalid_nesting:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/19/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/19/cts.https.html
new file mode 100644
index 0000000000..7fd8995cdd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/19/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:occlusion_query,disjoint_queries_with_same_query_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,begin_end:nesting:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,invalid_query_set:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:occlusion_query,query_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,query_type_and_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,invalid_query_set:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,general:timestamp_query,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:queryset_and_destination_buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:first_query_and_query_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_buffer_usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:destination_offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:resolve_buffer_oob:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,queries,resolveQuerySet:query_set_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:empty_bundle_list:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:color_formats_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_formats_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:depth_stencil_readonly_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,encoding,render_bundle:sample_count_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,error_scope:simple:*'>
+<meta name=variant content='?q=webgpu:api,validation,error_scope:empty:*'>
+<meta name=variant content='?q=webgpu:api,validation,error_scope:parent_scope:*'>
+<meta name=variant content='?q=webgpu:api,validation,error_scope:current_scope:*'>
+<meta name=variant content='?q=webgpu:api,validation,error_scope:balanced_siblings:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/2/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/2/cts.https.html
new file mode 100644
index 0000000000..89410c8078
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/2/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,buffers,threading:destroyed:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:empty:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:b2t2b:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:b2t2t2b:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,clearBuffer:clear:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:single:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:state_transitions:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:copy_order:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:zero_sized:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_color:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_depth:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:origins_and_extents:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:undefined_params:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow_depth_stencil:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes_copy_depth_stencil:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_indices:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_order:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/20/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/20/cts.https.html
new file mode 100644
index 0000000000..eb21d5a792
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/20/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,error_scope:balanced_nesting:*'>
+<meta name=variant content='?q=webgpu:api,validation,getBindGroupLayout:index_range,explicit_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,getBindGroupLayout:index_range,auto_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,getBindGroupLayout:unique_js_object,auto_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,getBindGroupLayout:unique_js_object,explicit_layout:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_related:bytes_per_row_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_usage_and_aspect:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_buffer_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:depth_stencil_format,copy_buffer_offset:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:texture_buffer_usages:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,buffer_texture_copies:device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_rows_per_image:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:copy_end_overflows_u64:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:required_bytes_in_copy:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:rows_per_image_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_bytes_per_row:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,layout_related:bound_on_offset:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:valid:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:texture,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:usage:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/21/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/21/cts.https.html
new file mode 100644
index 0000000000..d2480074f9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/21/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:mip_level:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:format:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:size_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:copy_rectangle:*'>
+<meta name=variant content='?q=webgpu:api,validation,query_set,create:count:*'>
+<meta name=variant content='?q=webgpu:api,validation,query_set,destroy:twice:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:writeBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyBufferToTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:copyTextureToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,buffer_mapped:map_command_recording_order:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,contexts:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_canvas,state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,contexts:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_offscreenCanvas,state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_image,crossOrigin:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:source_imageBitmap,state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,mipLevel:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:destination_texture,format:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/22/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/22/cts.https.html
new file mode 100644
index 0000000000..b7d9a0443d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/22/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,source:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,copyToTexture,CopyExternalImageToTexture:OOB,destination:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:beginOcclusionQuery:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:writeTimestamp:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,destroyed,query_set:resolveQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,submit:command_buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:buffer_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:ranges:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:usages:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeBuffer:buffer,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeTexture:texture_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeTexture:usages:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeTexture:sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,queue,writeTexture:texture,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,color_sparse:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,depth_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_and_bundle,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,color_sparse:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,depth_stencil_read_only_write_state:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/23/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/23/cts.https.html
new file mode 100644
index 0000000000..f2bd7c06ce
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/23/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,render_pass,attachment_compatibility:render_pass_or_bundle_and_pipeline,sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,one_color_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,one_depth_stencil_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,same_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,color_depth_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,layer_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:attachments,mip_level_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,empty:*'>
+<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,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,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:resolveTarget,sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,array_layer_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,mipmap_level_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,error_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,single_sample_count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,different_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,different_size:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:resolveTarget,format_supports_resolve:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment,sample_counts_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:depth_stencil_attachment:*'>
+<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/chunked/24/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/24/cts.https.html
new file mode 100644
index 0000000000..f524b4e131
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/24/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrites,query_set_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestamp_writes_location:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrite,query_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:timestampWrite,same_query_index:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,render_pass_descriptor:occlusionQuerySet,query_set_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,resolve:resolve_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_test:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_write:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:depth_write,frag_depth:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:stencil_test:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,depth_stencil_state:stencil_write:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:color_target_exists:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:targets_format_renderable:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachments:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachmentBytesPerSample,aligned:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:limits,maxColorAttachmentBytesPerSample,unaligned:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:targets_format_filterable:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:targets_blend:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:targets_write_mask:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,fragment_state:pipeline_output_targets,blend:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:location,mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:location,superset:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/25/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/25/cts.https.html
new file mode 100644
index 0000000000..74ea4bb85f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/25/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:location,subset:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:type:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:interpolation_type:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:interpolation_sampling:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:max_shader_variable_location:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:max_components_count,output:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,inter_stage:max_components_count,input:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,misc:basic:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,misc:vertex_state_only:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,misc:pipeline_layout,device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,multisample_state:count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,multisample_state:alpha_to_coverage,count:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,multisample_state:alpha_to_coverage,sample_mask:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:identifier,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:identifier,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:uninitialized,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:uninitialized,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,type_error,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,type_error,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,f16,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,overrides:value,validation_error,f16,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,primitive_state:strip_index_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,primitive_state:unclipped_depth:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/26/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/26/cts.https.html
new file mode 100644
index 0000000000..e4db92b95a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/26/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,shader_module:device_mismatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,shader_module:invalid,vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,shader_module:invalid,fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_buffer_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_attribute_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:max_vertex_buffer_array_stride_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_buffer_array_stride_limit_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_shaderLocation_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_shaderLocation_unique:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_input_location_limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_input_location_in_vertex_state:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_shader_type_matches_attribute_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_offset_alignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:vertex_attribute_contained_in_stride:*'>
+<meta name=variant content='?q=webgpu:api,validation,render_pipeline,vertex_state:many_attributes_overlapping:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_no_dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_compute_pass_with_one_dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_compute_pass_with_two_dispatches:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_no_draw:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_one_draw:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_encoder:subresources,buffer_usage_in_one_render_pass_with_two_draws:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,reset_buffer_usage_before_draw:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,buffer,in_pass_misc:subresources,buffer_usages_in_copy_and_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_color:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/27/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/27/cts.https.html
new file mode 100644
index 0000000000..ee9bf405f7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/27/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:subresources_and_binding_types_combination_for_aspect:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:shader_stages_and_visibility,storage_write:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:shader_stages_and_visibility,attachment_write:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:replaced_binding:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:bindings_in_bundle:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:unused_bindings_in_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,basic,render:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,pass_boundary,compute:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_pass_encoder:scope,pass_boundary,render:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachments:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,color_attachment_and_bind_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_attachment_and_bind_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,multiple_bind_groups:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_common:subresources,depth_stencil_texture_in_bind_groups:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_color_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_bind_group_on_same_index_depth_stencil_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,set_unused_bind_group:*'>
+<meta name=variant content='?q=webgpu:api,validation,resource_usages,texture,in_render_misc:subresources,texture_usages_in_copy_and_render_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,shader_module,entry_point:compute:*'>
+<meta name=variant content='?q=webgpu:api,validation,shader_module,entry_point:vertex:*'>
+<meta name=variant content='?q=webgpu:api,validation,shader_module,entry_point:fragment:*'>
+<meta name=variant content='?q=webgpu:api,validation,shader_module,overrides:id_conflict:*'>
+<meta name=variant content='?q=webgpu:api,validation,shader_module,overrides:name_conflict:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBuffer:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/28/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/28/cts.https.html
new file mode 100644
index 0000000000..1e73abddfd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/28/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createTexture,2d,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createView,2d,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createSampler:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroupLayout:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createBindGroup:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createPipelineLayout:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createShaderModule:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createComputePipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderPipeline:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createCommandEncoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createRenderBundleEncoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:createQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyBufferToTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,copyTextureToTexture:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,clearBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,writeTimestamp:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,resolveQuerySet:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,computePass,dispatch:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,draw:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:command,renderPass,renderBundle:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeBuffer:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/29/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/29/cts.https.html
new file mode 100644
index 0000000000..82a166b876
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/29/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,uncompressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,writeTexture,2d,compressed_format:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,canvas:*'>
+<meta name=variant content='?q=webgpu:api,validation,state,device_lost,destroy:queue,copyExternalImageToTexture,imageBitmap:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,destroy:base:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,destroy:twice:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,destroy:submit_a_destroyed_texture_as_attachment:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:create_texture:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:begin_render_pass:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:begin_render_bundle_encoder:*'>
+<meta name=variant content='?q=webgpu:api,validation,texture,rg11b10ufloat_renderable:create_render_pipeline:*'>
+<meta name=variant content='?q=webgpu:examples:test_name:*'>
+<meta name=variant content='?q=webgpu:examples:not_implemented_yet,without_plan:*'>
+<meta name=variant content='?q=webgpu:examples:not_implemented_yet,with_plan:*'>
+<meta name=variant content='?q=webgpu:examples:basic:*'>
+<meta name=variant content='?q=webgpu:examples:basic,async:*'>
+<meta name=variant content='?q=webgpu:examples:basic,plain_cases:*'>
+<meta name=variant content='?q=webgpu:examples:basic,plain_cases_private:*'>
+<meta name=variant content='?q=webgpu:examples:basic,builder_cases:*'>
+<meta name=variant content='?q=webgpu:examples:basic,builder_cases_subcases:*'>
+<meta name=variant content='?q=webgpu:examples:basic,builder_subcases:*'>
+<meta name=variant content='?q=webgpu:examples:basic,builder_subcases_short:*'>
+<meta name=variant content='?q=webgpu:examples:gpu,async:*'>
+<meta name=variant content='?q=webgpu:examples:gpu,buffers:*'>
+<meta name=variant content='?q=webgpu:examples:gpu,with_texture_compression,bc:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/3/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/3/cts.https.html
new file mode 100644
index 0000000000..c548ceb9da
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/3/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_before_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:one_bind_group_multiple_slots:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:bind_group_multiple_sets:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,programmable,state_tracking:compatible_pipelines:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_without_changing_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_without_changing_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:change_pipeline_before_and_after_vertex_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_vertex_buffer_but_not_used_in_draw:*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,state_tracking:set_index_buffer_before_non_indexed_draw:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute,basic:memcpy:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute,basic:large_dispatch:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:basic:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:numeric_id:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:precision:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:workgroup_size:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:shared_shader_module:*'>
+<meta name=variant content='?q=webgpu:api,operation,compute_pipeline,overrides:multi_entry_points:*'>
+<meta name=variant content='?q=webgpu:api,operation,device,lost:not_lost_on_gc:*'>
+<meta name=variant content='?q=webgpu:api,operation,device,lost:lost_on_destroy:*'>
+<meta name=variant content='?q=webgpu:api,operation,device,lost:same_object:*'>
+<meta name=variant content='?q=webgpu:api,operation,labels:object_has_descriptor_label:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:rw:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:wr:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:ww:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_draws_in_one_render_pass:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/30/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/30/cts.https.html
new file mode 100644
index 0000000000..17fb900ab5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/30/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:examples:gpu,with_texture_compression,etc2:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:BufferUsage,count:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:BufferUsage,values:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:TextureUsage,count:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:TextureUsage,values:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:ColorWrite,count:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:ColorWrite,values:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,count:*'>
+<meta name=variant content='?q=webgpu:idl,constants,flags:ShaderStage,values:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_arith:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_logical:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:binary_mixed:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:call:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:index_accessor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:assignment:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:type_constructor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,evaluation_order:member_accessor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_or:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_and:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bitwise:bitwise_exclusive_or:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:and:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:and_short_circuit:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:or:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:or_short_circuit:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:equals:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/31/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/31/cts.https.html
new file mode 100644
index 0000000000..f91e1a9f6d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/31/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,bool_logical:not_equals:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:addition:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:subtraction:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:multiplication:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:division:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_arithmetic:remainder:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:equals:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:not_equals:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:less_than:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:less_equals:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:greater_than:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,f32_logical:greater_equals:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,i32_arithmetic:addition:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,i32_arithmetic:subtraction:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,i32_arithmetic:multiplication:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,i32_arithmetic:division:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,i32_arithmetic:remainder:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:addition:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:subtraction:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:division:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:remainder:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication_scalar_vector:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,binary,u32_arithmetic:multiplication_vector_scalar:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_int:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/32/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/32/cts.https.html
new file mode 100644
index 0000000000..3ad2c39a44
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/32/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,abs:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acos:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,acosh:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,all:bool:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,any:bool:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,arrayLength:array:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asinh:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f32:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/33/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/33/cts.https.html
new file mode 100644
index 0000000000..2d89a48d30
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/33/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan2:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atanh:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAdd:add:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicAnd:and:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicCompareExchangeWeak:exchange:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicExchange:exchange:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicLoad:load:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMax:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMax:max:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMin:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicMin:min:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicOr:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicOr:or:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicStore:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicStore:store:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicSub:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicSub:sub:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicXor:stage:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/34/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/34/cts.https.html
new file mode 100644
index 0000000000..26118bcce3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/34/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atomicXor:xor:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ceil:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_int:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,clamp:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cos:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cosh:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countLeadingZeros:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countOneBits:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countOneBits:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,countTrailingZeros:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,cross:f16:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/35/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/35/cts.https.html
new file mode 100644
index 0000000000..2692ffa37e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/35/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,degrees:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,determinant:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,distance:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_int:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dot:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdx:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdxCoarse:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdxFine:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdy:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdyCoarse:f32:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/36/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/36/cts.https.html
new file mode 100644
index 0000000000..79277d99e1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/36/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,dpdyFine:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,exp2:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,extractBits:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,extractBits:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,faceForward:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstLeadingBit:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,firstTrailingBit:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,floor:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fma:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:abstract_float:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/37/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/37/cts.https.html
new file mode 100644
index 0000000000..467d037984
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/37/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fract:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:scalar_f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,frexp:vector_f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidth:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidthCoarse:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,fwidthFine:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,insertBits:integer:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,inversesqrt:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,ldexp:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,length:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log:f16:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/38/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/38/cts.https.html
new file mode 100644
index 0000000000..e80e64d29b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/38/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,log2:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:abstract_int:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,max:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:abstract_int:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,min:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:matching_abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:matching_f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:matching_f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:nonmatching_f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,mix:monmatching_f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec2_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec2_whole:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/39/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/39/cts.https.html
new file mode 100644
index 0000000000..b46895a8f9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/39/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec3_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec3_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec4_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f32_vec4_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec2_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec2_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec3_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec3_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec4_fract:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,modf:f16_vec4_whole:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,normalize:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16float:pack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16snorm:pack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack2x16unorm:pack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack4x8snorm:pack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pack4x8unorm:pack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,pow:f16:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/4/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/4/cts.https.html
new file mode 100644
index 0000000000..df1890201d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/4/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_draws_in_one_render_bundle:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,multiple_buffers:multiple_pairs_of_dispatches_in_one_compute_pass:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:rw:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:wr:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:ww:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_pass:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_draws_in_the_same_render_bundle:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,buffer,single_buffer:two_dispatches_in_the_same_compute_pass:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_store:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:rw,single_pass,load_resolve:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:wr:*'>
+<meta name=variant content='?q=webgpu:api,operation,memory_sync,texture,same_subresource:ww:*'>
+<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:without_work:*'>
+<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:with_work:*'>
+<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,serial:*'>
+<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel:*'>
+<meta name=variant content='?q=webgpu:api,operation,onSubmittedWorkDone:many,parallel_order:*'>
+<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:getBindGroupLayout_js_object:*'>
+<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:incompatible_with_explicit:*'>
+<meta name=variant content='?q=webgpu:api,operation,pipeline,default_layout:layout:*'>
+<meta name=variant content='?q=webgpu:api,operation,queue,writeBuffer:array_types:*'>
+<meta name=variant content='?q=webgpu:api,operation,queue,writeBuffer:multiple_writes_at_different_offsets_and_sizes:*'>
+<meta name=variant content='?q=webgpu:api,operation,reflection:buffer_reflection_attributes:*'>
+<meta name=variant content='?q=webgpu:api,operation,reflection:texture_reflection_attributes:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/40/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/40/cts.https.html
new file mode 100644
index 0000000000..c28d043dba
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/40/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,quantizeToF16:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,radians:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reflect:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f32_vec4:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,refract:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reverseBits:u32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,reverseBits:i32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,round:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,saturate:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,saturate:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,saturate:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,select:scalar:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,select:vector:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:abstract_float:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/41/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/41/cts.https.html
new file mode 100644
index 0000000000..13eff1789f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/41/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sign:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sin:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sinh:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,smoothstep:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,sqrt:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,step:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,storageBarrier:barrier:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tan:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,tanh:f16:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/42/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/42/cts.https.html
new file mode 100644
index 0000000000..c0bffe766a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/42/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:sampled:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:depth:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:storage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureDimension:external:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:sampled_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGather:depth_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureGatherCompare:sampled_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_1d:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_2d:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:sampled_3d:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:multisampled:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:depth:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:external:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureLoad:arrayed:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:sampled:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:arrayed:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/43/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/43/cts.https.html
new file mode 100644
index 0000000000..30eb586b56
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/43/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLayers:storage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:sampled:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumLevels:depth:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:sampled:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureNumSamples:depth:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:control_flow:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_1d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:sampled_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSample:depth_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:control_flow:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:sampled_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleBias:arrayed_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:control_flow:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:2d_coords:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/44/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/44/cts.https.html
new file mode 100644
index 0000000000..d87d4661ad
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/44/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompare:arrayed_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:control_flow:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleCompareLevel:arrayed_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleGrad:sampled_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:sampled_array_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureSampleLevel:depth_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_1d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_array_2d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,textureStore:store_3d_coords:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:abstract_float:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/45/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/45/cts.https.html
new file mode 100644
index 0000000000..aa8fddb4f1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/45/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,transpose:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,trunc:f16:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16float:unpack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16snorm:unpack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack2x16unorm:unpack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack4x8snorm:unpack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,unpack4x8unorm:unpack:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:stage:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,workgroupBarrier:barrier:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,unary,bool_logical:negation:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,unary,f32_arithmetic:negation:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,unary,i32_arithmetic:negation:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,atomicity:atomicity:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_load:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_load_store:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,barrier:workgroup_barrier_store_store:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corr:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:coww:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:cowr:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corw1:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,coherence:corw2:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:message_passing:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/46/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/46/cts.https.html
new file mode 100644
index 0000000000..048c73733e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/46/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:store:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:load_buffer:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:read:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:store_buffer:*'>
+<meta name=variant content='?q=webgpu:shader,execution,memory_model,weak:2_plus_2_write:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:struct_implicit:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:struct_explicit:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:struct_nested:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:array_of_vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:array_of_struct:*'>
+<meta name=variant content='?q=webgpu:shader,execution,padding:vec3:*'>
+<meta name=variant content='?q=webgpu:shader,execution,robust_access:linear_memory:*'>
+<meta name=variant content='?q=webgpu:shader,execution,robust_access_vertex:vertex_buffer_access:*'>
+<meta name=variant content='?q=webgpu:shader,execution,shader_io,compute_builtins:inputs:*'>
+<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_buffer:*'>
+<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_between_stages:*'>
+<meta name=variant content='?q=webgpu:shader,execution,shader_io,shared_structs:shared_with_non_entry_point_function:*'>
+<meta name=variant content='?q=webgpu:shader,execution,zero_init:compute,zero_init:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,align:align_parsing:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,align:align_required_alignment:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,blankspace:null_characters:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,blankspace:blankspace:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,builtin:parse:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,comments:comments:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,comments:line_comment_eof:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/47/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/47/cts.https.html
new file mode 100644
index 0000000000..a1455d2756
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/47/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,validation,parse,comments:line_comment_terminators:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,comments:unterminated_block_comment:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,identifiers:identifiers:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,identifiers:non_normalized:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:bools:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:abstract_int:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:i32:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:u32:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:f32:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,literal:f16:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:module_scope_single:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:module_scope_multiple:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_enable:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_struct_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_member:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_func_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_type_alias_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_return:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_call:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_module_const_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_fn_const_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_module_var_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_fn_var_decl:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_let_decl:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/48/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/48/cts.https.html
new file mode 100644
index 0000000000..0ee13cb4fd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/48/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_discard:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_assignment:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_fn_static_assert:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:function_body_single:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:function_body_multiple:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:compound_statement_single:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:compound_statement_multiple:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_compound_statement:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_if:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_if_else:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_switch:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_case:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_case_break:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_default_case:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_default_case_break:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_for:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_for_break:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_loop:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_loop_break:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_loop_break_if:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_loop_continue:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_continuing:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_while:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_while_break:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,semicolon:after_while_continue:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/49/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/49/cts.https.html
new file mode 100644
index 0000000000..94244c93b4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/49/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,validation,parse,source:valid_source:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,source:empty:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,source:invalid_source:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,static_assert:parse:*'>
+<meta name=variant content='?q=webgpu:shader,validation,parse,var_and_let:initializer_type:*'>
+<meta name=variant content='?q=webgpu:shader,validation,resource_interface,bindings:single_entry_point:*'>
+<meta name=variant content='?q=webgpu:shader,validation,resource_interface,bindings:different_entry_points:*'>
+<meta name=variant content='?q=webgpu:shader,validation,resource_interface,bindings:binding_attributes:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:stage_inout:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:type:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:nesting:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:duplicates:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:missing_vertex_position:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,builtins:reuse_builtin_name:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_param:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_param_struct:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_return_type:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,entry_point:missing_attribute_on_return_type_struct:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,entry_point:no_entry_point_provided:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:type_and_sampling:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:require_location:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:integral_types:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,interpolate:duplicate:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:valid_only_with_vertex_position_builtin:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:not_valid_on_user_defined_io:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/5/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/5/cts.https.html
new file mode 100644
index 0000000000..9df144950d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/5/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,reflection:query_set_reflection_attributes:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:stored:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:loaded:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:srgb:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:layout:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,clear_value:stencil_clear_value:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,resolve:render_pass_resolve:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_with_depth_stencil_attachment:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,multiple_color_attachments:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,depth_stencil_attachment_only:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pass,storeop2:storeOp_controls_whether_1x1_drawn_quad_is_stored:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,culling_tests:culling:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,overrides:basic:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,overrides:precision:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,overrides:shared_shader_module:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,overrides:multi_entry_points:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,attachments:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count,blend:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,primitive_topology:basic:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,primitive_topology:unaligned_vertex_count:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,sample_mask:final_output:*'>
+<meta name=variant content='?q=webgpu:api,operation,render_pipeline,vertex_only_render_pipeline:draw_depth_and_stencil_with_vertex_only_pipeline:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,basic:clear:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/50/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/50/cts.https.html
new file mode 100644
index 0000000000..66e37df757
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/50/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:invalid_use_of_parameters:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,invariant:duplicate:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:stage_inout:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:type:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:nesting:*'>
+<meta name=variant content='?q=webgpu:shader,validation,shader_io,locations:duplicates:*'>
+<meta name=variant content='?q=webgpu:shader,validation,static_assert,static_assert:constant_expression:*'>
+<meta name=variant content='?q=webgpu:shader,validation,static_assert,static_assert:evaluation_stage:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:unorm_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:snorm_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:uint_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:sint_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:float_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texel_data:ufloat_texel_data_in_shader:*'>
+<meta name=variant content='?q=webgpu:util,texture,texture_ok:float32:*'>
+<meta name=variant content='?q=webgpu:util,texture,texture_ok:norm:*'>
+<meta name=variant content='?q=webgpu:util,texture,texture_ok:snorm_min:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:defaults:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:device:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:format:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:usage:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:alpha_mode:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:size_zero_before_configure:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:size_zero_after_configure:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,configure:viewFormats:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/51/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/51/cts.https.html
new file mode 100644
index 0000000000..db8ad7c5cc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/51/cts.https.html
@@ -0,0 +1,58 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:web_platform,canvas,context_creation:return_type:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,getCurrentTexture:configured:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,getCurrentTexture:single_frames:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,getCurrentTexture:multiple_frames:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,getCurrentTexture:resize:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,getPreferredCanvasFormat:value:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,snapshot:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,uploadToWebGL:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:offscreenCanvas,snapshot:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:drawTo2DCanvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:transferToImageBitmap_unconfigured_nonzero_size:*'>
+<meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:transferToImageBitmap_zero_size:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:copy_subrect_from_ImageData:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:copy_subrect_from_2D_Canvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:color_space_conversion:*'>
+<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,sample:*'>
+<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,expired:*'>
+<meta name=variant content='?q=webgpu:web_platform,external_texture,video:importExternalTexture,compute:*'>
+<meta name=variant content='?q=webgpu:web_platform,worker,worker:worker:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/6/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/6/cts.https.html
new file mode 100644
index 0000000000..d6d9a9c0c1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/6/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,rendering,basic:fullscreen_quad:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,basic:large_draw:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blending,GPUBlendComponent:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blending,formats:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blending,clamping:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blend_constant,initial:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blend_constant,setting:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:blend_constant,not_inherited:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:color_write_mask,channel_work:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,color_target_state:color_write_mask,blending_disabled:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_disabled:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_write_disabled:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_test_fail:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:depth_compare_func:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth:reverse_depth:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth_bias:depth_bias:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth_bias:depth_bias_24bit_format:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_clamp_and_clip:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,draw:arguments:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,draw:default_arguments:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,draw:vertex_attributes,basic:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,draw:vertex_attributes,formats:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,draw:largeish_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,indirect_draw:basics:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/7/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/7/cts.https.html
new file mode 100644
index 0000000000..f1f9e5ec02
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/7/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_compare_func:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_passOp_operation:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_failOp_operation:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_depthFailOp_operation:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_read_write_mask:*'>
+<meta name=variant content='?q=webgpu:api,operation,rendering,stencil:stencil_reference_initialized:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:partial_write_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:map_whole_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:map_partial_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_whole_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:mapped_at_creation_partial_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_buffer_copy_source:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_buffer_to_texture:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:resolve_query_set_to_partial_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:copy_texture_to_partial_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:uniform_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:readonly_storage_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:storage_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:vertex_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:index_buffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_draw_indirect:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,buffer:indirect_buffer_for_dispatch_indirect:*'>
+<meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:*'>
+<meta name=variant content='?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_checkerboard:*'>
+<meta name=variant content='?q=webgpu:api,operation,sampling,anisotropy:anisotropic_filter_mipmap_color:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/8/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/8/cts.https.html
new file mode 100644
index 0000000000..b23ee54868
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/8/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:compilationInfo_returns:*'>
+<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:line_number_and_position:*'>
+<meta name=variant content='?q=webgpu:api,operation,shader_module,compilation_info:offset_and_length:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,format_reinterpretation:texture_binding:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,format_reinterpretation:render_and_resolve_attachment:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,read:format:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,read:dimension:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,read:aspect:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,write:format:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,write:dimension:*'>
+<meta name=variant content='?q=webgpu:api,operation,texture_view,write:aspect:*'>
+<meta name=variant content='?q=webgpu:api,operation,uncapturederror:constructor:*'>
+<meta name=variant content='?q=webgpu:api,operation,uncapturederror:iff_uncaptured:*'>
+<meta name=variant content='?q=webgpu:api,operation,uncapturederror:only_original_device_is_event_target:*'>
+<meta name=variant content='?q=webgpu:api,operation,uncapturederror:uncapturederror_from_non_originating_thread:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_format_to_shader_format_conversion:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:setVertexBuffer_offset_and_attribute_offset:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:non_zero_array_stride_and_attribute_offset:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:buffers_with_varying_step_mode:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_overlapped:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:vertex_buffer_used_multiple_times_interleaved:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:array_stride_zero:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:discontiguous_location_and_attribs:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/chunked/9/cts.https.html b/testing/web-platform/mozilla/tests/webgpu/chunked/9/cts.https.html
new file mode 100644
index 0000000000..d0ebb3eae6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/chunked/9/cts.https.html
@@ -0,0 +1,59 @@
+<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
+<!--
+ This test suite is built from the TypeScript sources at:
+ https://github.com/gpuweb/cts
+
+ If you are debugging WebGPU conformance tests, it's highly recommended that
+ you use the standalone interactive runner in that repository, which
+ provides tools for easier debugging and editing (source maps, debug
+ logging, warn/skip functionality, etc.)
+
+ NOTE:
+ The WPT version of this file is generated with *one variant per test spec
+ file*. If your harness needs more fine-grained suppressions, you'll need to
+ generate your own variants list from your suppression list.
+ See `tools/gen_wpt_cts_html` to do this.
+
+ When run under browser CI, the original cts.https.html should be skipped, and
+ this alternate version should be run instead, under a non-exported WPT test
+ directory (e.g. Chromium's wpt_internal).
+-->
+
+<!doctype html>
+<title>WebGPU CTS</title>
+<meta charset=utf-8>
+<link rel=help href='https://gpuweb.github.io/gpuweb/'>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+ const loadWebGPUExpectations = undefined;
+ const shouldWebGPUCTSFailOnWarnings = undefined;
+</script>
+<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>
+
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,uint16:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,uint32:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,change_pipeline_after_setIndexBuffer:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,setIndexBuffer_before_setPipeline:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:index_format,setIndexBuffer_different_formats:*'>
+<meta name=variant content='?q=webgpu:api,operation,vertex_state,index_format:primitive_restart:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,create:size:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,create:limit:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,create:usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,create:createBuffer_invalid_and_oom:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:all_usages:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:error_buffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:twice:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,destroy:while_mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,usage:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,invalidBuffer:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,destroyed:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappedAtCreation:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mapped:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,mappingPending:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,sizeUnspecifiedOOB:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeAlignment:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeOOB:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,earlyRejection:*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,abort_over_invalid_error:*'>
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js
new file mode 100644
index 0000000000..e426ffbbc9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js
@@ -0,0 +1,89 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+
+/** DataCache is an interface to a data store used to hold cached data */
+export class DataCache {
+ /** setDataStore() sets the backing data store used by the data cache */
+ setStore(dataStore) {
+ this.dataStore = dataStore;
+ }
+
+ /** setDebugLogger() sets the verbose logger */
+ setDebugLogger(logger) {
+ this.debugLogger = logger;
+ }
+
+ /**
+ * fetch() retrieves cacheable data from the data cache, first checking the
+ * in-memory cache, then the data store (if specified), then resorting to
+ * building the data and storing it in the cache.
+ */
+ async fetch(cacheable) {
+ // First check the in-memory cache
+ let data = this.cache.get(cacheable.path);
+ if (data !== undefined) {
+ this.log('in-memory cache hit');
+ return Promise.resolve(data);
+ }
+ this.log('in-memory cache miss');
+ // In in-memory cache miss.
+ // Next, try the data store.
+ if (this.dataStore !== null && !this.unavailableFiles.has(cacheable.path)) {
+ let serialized;
+ try {
+ serialized = await this.dataStore.load(cacheable.path);
+ this.log('loaded serialized');
+ } catch (err) {
+ // not found in data store
+ this.log(`failed to load (${cacheable.path}): ${err}`);
+ this.unavailableFiles.add(cacheable.path);
+ }
+ if (serialized !== undefined) {
+ this.log(`deserializing`);
+ data = cacheable.deserialize(serialized);
+ this.cache.set(cacheable.path, data);
+ return data;
+ }
+ }
+ // Not found anywhere. Build the data, and cache for future lookup.
+ this.log(`cache: building (${cacheable.path})`);
+ data = await cacheable.build();
+ this.cache.set(cacheable.path, data);
+ return data;
+ }
+
+ log(msg) {
+ if (this.debugLogger !== null) {
+ this.debugLogger(`DataCache: ${msg}`);
+ }
+ }
+
+ cache = new Map();
+ unavailableFiles = new Set();
+ dataStore = null;
+ debugLogger = null;
+}
+
+/** The data cache */
+export const dataCache = new DataCache();
+
+/** true if the current process is building the cache */
+let isBuildingDataCache = false;
+
+/** @returns true if the data cache is currently being built */
+export function getIsBuildingDataCache() {
+ return isBuildingDataCache;
+}
+
+/** Sets whether the data cache is currently being built */
+export function setIsBuildingDataCache(value = true) {
+ isBuildingDataCache = value;
+}
+
+/**
+ * Cacheable is the interface to something that can be stored into the
+ * DataCache.
+ * The 'npm run gen_cache' tool will look for module-scope variables of this
+ * interface, with the name `d`.
+ */
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js
new file mode 100644
index 0000000000..1611e9a742
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js
@@ -0,0 +1,310 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../util/util.js';
+
+export class SkipTestCase extends Error {}
+export class UnexpectedPassError extends Error {}
+
+export { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';
+
+/** The fully-general type for params passed to a test function invocation. */
+
+export class SubcaseBatchState {
+ constructor(params) {
+ this._params = params;
+ }
+
+ /**
+ * Returns the case parameters for this test fixture shared state. Subcase params
+ * are not included.
+ */
+ get params() {
+ return this._params;
+ }
+
+ /**
+ * Runs before the `.before()` function.
+ * @internal MAINTENANCE_TODO: Make this not visible to test code?
+ */
+ async init() {}
+ /**
+ * Runs between the `.before()` function and the subcases.
+ * @internal MAINTENANCE_TODO: Make this not visible to test code?
+ */
+ async postInit() {}
+ /**
+ * Runs after all subcases finish.
+ * @internal MAINTENANCE_TODO: Make this not visible to test code?
+ */
+ async finalize() {}
+}
+
+/**
+ * A Fixture is a class used to instantiate each test sub/case at run time.
+ * A new instance of the Fixture is created for every single test subcase
+ * (i.e. every time the test function is run).
+ */
+export class Fixture {
+ /**
+ * Interface for recording logs and test status.
+ *
+ * @internal
+ */
+
+ eventualExpectations = [];
+ numOutstandingAsyncExpectations = 0;
+ objectsToCleanUp = [];
+
+ static MakeSharedState(params) {
+ return new SubcaseBatchState(params);
+ }
+
+ /** @internal */
+ constructor(sharedState, rec, params) {
+ this._sharedState = sharedState;
+ this.rec = rec;
+ this._params = params;
+ }
+
+ /**
+ * Returns the (case+subcase) parameters for this test function invocation.
+ */
+ get params() {
+ return this._params;
+ }
+
+ /**
+ * Gets the test fixture's shared state. This object is shared between subcases
+ * within the same testcase.
+ */
+ get sharedState() {
+ return this._sharedState;
+ }
+
+ /**
+ * Override this to do additional pre-test-function work in a derived fixture.
+ * This has to be a member function instead of an async `createFixture` function, because
+ * we need to be able to ergonomically override it in subclasses.
+ *
+ * @internal MAINTENANCE_TODO: Make this not visible to test code?
+ */
+ async init() {}
+
+ /**
+ * Override this to do additional post-test-function work in a derived fixture.
+ *
+ * Called even if init was unsuccessful.
+ *
+ * @internal MAINTENANCE_TODO: Make this not visible to test code?
+ */
+ async finalize() {
+ assert(
+ this.numOutstandingAsyncExpectations === 0,
+ 'there were outstanding immediateAsyncExpectations (e.g. expectUncapturedError) at the end of the test'
+ );
+
+ // Loop to exhaust the eventualExpectations in case they chain off each other.
+ while (this.eventualExpectations.length) {
+ const p = this.eventualExpectations.shift();
+ try {
+ await p;
+ } catch (ex) {
+ this.rec.threw(ex);
+ }
+ }
+
+ // And clean up any objects now that they're done being used.
+ for (const o of this.objectsToCleanUp) {
+ if ('getExtension' in o) {
+ const WEBGL_lose_context = o.getExtension('WEBGL_lose_context');
+ if (WEBGL_lose_context) WEBGL_lose_context.loseContext();
+ } else if ('destroy' in o) {
+ o.destroy();
+ } else {
+ o.close();
+ }
+ }
+ }
+
+ /**
+ * Tracks an object to be cleaned up after the test finishes.
+ *
+ * MAINTENANCE_TODO: Use this in more places. (Will be easier once .destroy() is allowed on
+ * invalid objects.)
+ */
+ trackForCleanup(o) {
+ this.objectsToCleanUp.push(o);
+ return o;
+ }
+
+ /** Tracks an object, if it's destroyable, to be cleaned up after the test finishes. */
+ tryTrackForCleanup(o) {
+ if (typeof o === 'object' && o !== null) {
+ if (
+ 'destroy' in o ||
+ 'close' in o ||
+ o instanceof WebGLRenderingContext ||
+ o instanceof WebGL2RenderingContext
+ ) {
+ this.objectsToCleanUp.push(o);
+ }
+ }
+ return o;
+ }
+
+ /** Log a debug message. */
+ debug(msg) {
+ this.rec.debug(new Error(msg));
+ }
+
+ /** Throws an exception marking the subcase as skipped. */
+ skip(msg) {
+ throw new SkipTestCase(msg);
+ }
+
+ /** Log a warning and increase the result status to "Warn". */
+ warn(msg) {
+ this.rec.warn(new Error(msg));
+ }
+
+ /** Log an error and increase the result status to "ExpectFailed". */
+ fail(msg) {
+ this.rec.expectationFailed(new Error(msg));
+ }
+
+ /**
+ * Wraps an async function. Tracks its status to fail if the test tries to report a test status
+ * before the async work has finished.
+ */
+ async immediateAsyncExpectation(fn) {
+ this.numOutstandingAsyncExpectations++;
+ const ret = await fn();
+ this.numOutstandingAsyncExpectations--;
+ return ret;
+ }
+
+ /**
+ * Wraps an async function, passing it an `Error` object recording the original stack trace.
+ * The async work will be implicitly waited upon before reporting a test status.
+ */
+ eventualAsyncExpectation(fn) {
+ const promise = fn(new Error());
+ this.eventualExpectations.push(promise);
+ }
+
+ expectErrorValue(expectedError, ex, niceStack) {
+ if (!(ex instanceof Error)) {
+ niceStack.message = `THREW non-error value, of type ${typeof ex}: ${ex}`;
+ this.rec.expectationFailed(niceStack);
+ return;
+ }
+ const actualName = ex.name;
+ if (expectedError !== true && actualName !== expectedError) {
+ niceStack.message = `THREW ${actualName}, instead of ${expectedError}: ${ex}`;
+ this.rec.expectationFailed(niceStack);
+ } else {
+ niceStack.message = `OK: threw ${actualName}: ${ex.message}`;
+ this.rec.debug(niceStack);
+ }
+ }
+
+ /** Expect that the provided promise resolves (fulfills). */
+ shouldResolve(p, msg) {
+ this.eventualAsyncExpectation(async niceStack => {
+ const m = msg ? ': ' + msg : '';
+ try {
+ await p;
+ niceStack.message = 'resolved as expected' + m;
+ } catch (ex) {
+ niceStack.message = `REJECTED${m}`;
+ if (ex instanceof Error) {
+ niceStack.message += '\n' + ex.message;
+ }
+ this.rec.expectationFailed(niceStack);
+ }
+ });
+ }
+
+ /** Expect that the provided promise rejects, with the provided exception name. */
+ shouldReject(expectedName, p, msg) {
+ this.eventualAsyncExpectation(async niceStack => {
+ const m = msg ? ': ' + msg : '';
+ try {
+ await p;
+ niceStack.message = 'DID NOT REJECT' + m;
+ this.rec.expectationFailed(niceStack);
+ } catch (ex) {
+ niceStack.message = 'rejected as expected' + m;
+ this.expectErrorValue(expectedName, ex, niceStack);
+ }
+ });
+ }
+
+ /**
+ * Expect that the provided function throws.
+ * If an `expectedName` is provided, expect that the throw exception has that name.
+ */
+ shouldThrow(expectedError, fn, msg) {
+ const m = msg ? ': ' + msg : '';
+ try {
+ fn();
+ if (expectedError === false) {
+ this.rec.debug(new Error('did not throw, as expected' + m));
+ } else {
+ this.rec.expectationFailed(new Error('unexpectedly did not throw' + m));
+ }
+ } catch (ex) {
+ if (expectedError === false) {
+ this.rec.expectationFailed(new Error('threw unexpectedly' + m));
+ } else {
+ this.expectErrorValue(expectedError, ex, new Error(m));
+ }
+ }
+ }
+
+ /** Expect that a condition is true. */
+ expect(cond, msg) {
+ if (cond) {
+ const m = msg ? ': ' + msg : '';
+ this.rec.debug(new Error('expect OK' + m));
+ } else {
+ this.rec.expectationFailed(new Error(msg));
+ }
+ return cond;
+ }
+
+ /**
+ * If the argument is an `Error`, fail (or warn). If it's `undefined`, no-op.
+ * If the argument is an array, apply the above behavior on each of elements.
+ */
+ expectOK(error, { mode = 'fail', niceStack } = {}) {
+ const handleError = error => {
+ if (error instanceof Error) {
+ if (niceStack) {
+ error.stack = niceStack.stack;
+ }
+ if (mode === 'fail') {
+ this.rec.expectationFailed(error);
+ } else if (mode === 'warn') {
+ this.rec.warn(error);
+ } else {
+ unreachable();
+ }
+ }
+ };
+
+ if (Array.isArray(error)) {
+ for (const e of error) {
+ handleError(e);
+ }
+ } else {
+ handleError(error);
+ }
+ }
+
+ eventualExpectOK(error, { mode = 'fail' } = {}) {
+ this.eventualAsyncExpectation(async niceStack => {
+ this.expectOK(await error, { mode, niceStack });
+ });
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js
new file mode 100644
index 0000000000..787911f964
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js
@@ -0,0 +1,213 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { mergeParams } from '../internal/params_utils.js';
+import { stringifyPublicParams } from '../internal/query/stringify_params.js';
+import { assert, mapLazy } from '../util/util.js';
+
+// ================================================================
+// "Public" ParamsBuilder API / Documentation
+// ================================================================
+
+/**
+ * Provides doc comments for the methods of CaseParamsBuilder and SubcaseParamsBuilder.
+ * (Also enforces rough interface match between them.)
+ */
+
+/**
+ * Base class for `CaseParamsBuilder` and `SubcaseParamsBuilder`.
+ */
+export class ParamsBuilderBase {
+ constructor(cases) {
+ this.cases = cases;
+ }
+
+ /**
+ * Hidden from test files. Use `builderIterateCasesWithSubcases` to access this.
+ */
+}
+
+/**
+ * Calls the (normally hidden) `iterateCasesWithSubcases()` method.
+ */
+export function builderIterateCasesWithSubcases(builder) {
+ return builder.iterateCasesWithSubcases();
+}
+
+/**
+ * Builder for combinatorial test **case** parameters.
+ *
+ * CaseParamsBuilder is immutable. Each method call returns a new, immutable object,
+ * modifying the list of cases according to the method called.
+ *
+ * This means, for example, that the `unit` passed into `TestBuilder.params()` can be reused.
+ */
+export class CaseParamsBuilder extends ParamsBuilderBase {
+ *iterateCasesWithSubcases() {
+ for (const a of this.cases()) {
+ yield [a, undefined];
+ }
+ }
+
+ [Symbol.iterator]() {
+ return this.cases();
+ }
+
+ /** @inheritDoc */
+ expandWithParams(expander) {
+ const newGenerator = expanderGenerator(this.cases, expander);
+ return new CaseParamsBuilder(() => newGenerator({}));
+ }
+
+ /** @inheritDoc */
+ expand(key, expander) {
+ return this.expandWithParams(function* (p) {
+ for (const value of expander(p)) {
+ yield { [key]: value };
+ }
+ });
+ }
+
+ /** @inheritDoc */
+ combineWithParams(newParams) {
+ assertNotGenerator(newParams);
+ const seenValues = new Set();
+ for (const params of newParams) {
+ const paramsStr = stringifyPublicParams(params);
+ assert(!seenValues.has(paramsStr), `Duplicate entry in combine[WithParams]: ${paramsStr}`);
+ seenValues.add(paramsStr);
+ }
+
+ return this.expandWithParams(() => newParams);
+ }
+
+ /** @inheritDoc */
+ combine(key, values) {
+ assertNotGenerator(values);
+ const mapped = mapLazy(values, v => ({ [key]: v }));
+ return this.combineWithParams(mapped);
+ }
+
+ /** @inheritDoc */
+ filter(pred) {
+ const newGenerator = filterGenerator(this.cases, pred);
+ return new CaseParamsBuilder(() => newGenerator({}));
+ }
+
+ /** @inheritDoc */
+ unless(pred) {
+ return this.filter(x => !pred(x));
+ }
+
+ /**
+ * "Finalize" the list of cases and begin defining subcases.
+ * Returns a new SubcaseParamsBuilder. Methods called on SubcaseParamsBuilder
+ * generate new subcases instead of new cases.
+ */
+ beginSubcases() {
+ return new SubcaseParamsBuilder(
+ () => this.cases(),
+ function* () {
+ yield {};
+ }
+ );
+ }
+}
+
+/**
+ * The unit CaseParamsBuilder, representing a single case with no params: `[ {} ]`.
+ *
+ * `punit` is passed to every `.params()`/`.paramsSubcasesOnly()` call, so `kUnitCaseParamsBuilder`
+ * is only explicitly needed if constructing a ParamsBuilder outside of a test builder.
+ */
+export const kUnitCaseParamsBuilder = new CaseParamsBuilder(function* () {
+ yield {};
+});
+
+/**
+ * Builder for combinatorial test _subcase_ parameters.
+ *
+ * SubcaseParamsBuilder is immutable. Each method call returns a new, immutable object,
+ * modifying the list of subcases according to the method called.
+ */
+export class SubcaseParamsBuilder extends ParamsBuilderBase {
+ constructor(cases, generator) {
+ super(cases);
+ this.subcases = generator;
+ }
+
+ *iterateCasesWithSubcases() {
+ for (const caseP of this.cases()) {
+ const subcases = Array.from(this.subcases(caseP));
+ if (subcases.length) {
+ yield [caseP, subcases];
+ }
+ }
+ }
+
+ /** @inheritDoc */
+ expandWithParams(expander) {
+ return new SubcaseParamsBuilder(this.cases, expanderGenerator(this.subcases, expander));
+ }
+
+ /** @inheritDoc */
+ expand(key, expander) {
+ return this.expandWithParams(function* (p) {
+ for (const value of expander(p)) {
+ // TypeScript doesn't know here that NewPKey is always a single literal string type.
+ yield { [key]: value };
+ }
+ });
+ }
+
+ /** @inheritDoc */
+ combineWithParams(newParams) {
+ assertNotGenerator(newParams);
+ return this.expandWithParams(() => newParams);
+ }
+
+ /** @inheritDoc */
+ combine(key, values) {
+ assertNotGenerator(values);
+ return this.expand(key, () => values);
+ }
+
+ /** @inheritDoc */
+ filter(pred) {
+ return new SubcaseParamsBuilder(this.cases, filterGenerator(this.subcases, pred));
+ }
+
+ /** @inheritDoc */
+ unless(pred) {
+ return this.filter(x => !pred(x));
+ }
+}
+
+function expanderGenerator(baseGenerator, expander) {
+ return function* (base) {
+ for (const a of baseGenerator(base)) {
+ for (const b of expander(mergeParams(base, a))) {
+ yield mergeParams(a, b);
+ }
+ }
+ };
+}
+
+function filterGenerator(baseGenerator, pred) {
+ return function* (base) {
+ for (const a of baseGenerator(base)) {
+ if (pred(mergeParams(base, a))) {
+ yield a;
+ }
+ }
+ };
+}
+
+/** Assert an object is not a Generator (a thing returned from a generator function). */
+function assertNotGenerator(x) {
+ if ('constructor' in x) {
+ assert(
+ x.constructor !== (function* () {})().constructor,
+ 'Argument must not be a generator, as generators are not reusable'
+ );
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js
new file mode 100644
index 0000000000..72eabeda4e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js
@@ -0,0 +1,111 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * Base path for resources. The default value is correct for non-worker WPT, but standalone and
+ * workers must access resources using a different base path, so this is overridden in
+ * `test_worker-worker.ts` and `standalone.ts`.
+ */ let baseResourcePath = './resources';
+let crossOriginHost = '';
+
+function getAbsoluteBaseResourcePath(path) {
+ // Path is already an absolute one.
+ if (path[0] === '/') {
+ return path;
+ }
+
+ // Path is relative
+ const relparts = window.location.pathname.split('/');
+ relparts.pop();
+ const pathparts = path.split('/');
+
+ let i;
+ for (i = 0; i < pathparts.length; ++i) {
+ switch (pathparts[i]) {
+ case '':
+ break;
+ case '.':
+ break;
+ case '..':
+ relparts.pop();
+ break;
+ default:
+ relparts.push(pathparts[i]);
+ break;
+ }
+ }
+
+ return relparts.join('/');
+}
+
+function runningOnLocalHost() {
+ const hostname = window.location.hostname;
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';
+}
+
+/**
+ * Get a path to a resource in the `resources` directory relative to the current execution context
+ * (html file or worker .js file), for `fetch()`, `<img>`, `<video>`, etc but from cross origin host.
+ * Provide onlineUrl if the case running online.
+ * @internal MAINTENANCE_TODO: Cases may run in the LAN environment (not localhost but no internet
+ * access). We temporarily use `crossOriginHost` to configure the cross origin host name in that situation.
+ * But opening to auto-detect mechanism or other solutions.
+ */
+export function getCrossOriginResourcePath(pathRelativeToResourcesDir, onlineUrl = '') {
+ // A cross origin host has been configured. Use this to load resource.
+ if (crossOriginHost !== '') {
+ return (
+ crossOriginHost +
+ getAbsoluteBaseResourcePath(baseResourcePath) +
+ '/' +
+ pathRelativeToResourcesDir
+ );
+ }
+
+ // Using 'localhost' and '127.0.0.1' trick to load cross origin resource. Set cross origin host name
+ // to 'localhost' if case is not running in 'localhost' domain. Otherwise, use '127.0.0.1'.
+ // host name to locahost unless the server running in
+ if (runningOnLocalHost()) {
+ let crossOriginHostName = '';
+ if (location.hostname === 'localhost') {
+ crossOriginHostName = 'http://127.0.0.1';
+ } else {
+ crossOriginHostName = 'http://localhost';
+ }
+
+ return (
+ crossOriginHostName +
+ ':' +
+ location.port +
+ getAbsoluteBaseResourcePath(baseResourcePath) +
+ '/' +
+ pathRelativeToResourcesDir
+ );
+ }
+
+ return onlineUrl;
+}
+
+/**
+ * Get a path to a resource in the `resources` directory, relative to the current execution context
+ * (html file or worker .js file), for `fetch()`, `<img>`, `<video>`, etc. Pass the cross origin host
+ * name if wants to load resoruce from cross origin host.
+ */
+export function getResourcePath(pathRelativeToResourcesDir) {
+ return baseResourcePath + '/' + pathRelativeToResourcesDir;
+}
+
+/**
+ * Set the base resource path (path to the `resources` directory relative to the current
+ * execution context).
+ */
+export function setBaseResourcePath(path) {
+ baseResourcePath = path;
+}
+
+/**
+ * Set the cross origin host and cases related to cross origin
+ * will load resource from the given host.
+ */
+export function setCrossOriginHost(host) {
+ crossOriginHost = host;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js
new file mode 100644
index 0000000000..de016471cd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js
@@ -0,0 +1,10 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+
+export const globalTestConfig = {
+ maxSubcasesInFlight: 500,
+ testHeartbeatCallback: () => {},
+ noRaceWithRejectOnTimeout: false,
+ unrollConstEvalLoops: false,
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js
new file mode 100644
index 0000000000..2d1d3c1c07
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js
@@ -0,0 +1,3 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export { makeTestGroup } from '../internal/test_group.js';
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js
new file mode 100644
index 0000000000..e9aa0f66fc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js
@@ -0,0 +1,96 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from '../util/util.js';
+import { parseQuery } from './query/parseQuery.js';
+
+
+import { loadTreeForQuery } from './tree.js';
+
+// A listing file, e.g. either of:
+// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>)
+// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Base class for DefaultTestFileLoader and FakeTestFileLoader.
+export class TestFileLoader extends EventTarget {
+
+
+
+ importSpecFile(suite, path) {
+ const url = `${suite}/${path.join('/')}.spec.js`;
+ this.dispatchEvent(
+ new MessageEvent('import', { data: { url } }));
+
+ return this.import(url);
+ }
+
+ async loadTree(query, subqueriesToExpand = []) {
+ const tree = await loadTreeForQuery(
+ this,
+ query,
+ subqueriesToExpand.map((s) => {
+ const q = parseQuery(s);
+ assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\n ${q}`);
+ return q;
+ }));
+
+ this.dispatchEvent(new MessageEvent('finish'));
+ return tree;
+ }
+
+ async loadCases(query) {
+ const tree = await this.loadTree(query);
+ return tree.iterateLeaves();
+ }
+}
+
+export class DefaultTestFileLoader extends TestFileLoader {
+ async listing(suite) {
+ return (await import(`../../${suite}/listing.js`)).listing;
+ }
+
+ import(path) {
+ return import(`../../${path}`);
+ }
+}
+//# sourceMappingURL=file_loader.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map
new file mode 100644
index 0000000000..3a5d5b17f4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"file_loader.js","names":["assert","parseQuery","loadTreeForQuery","TestFileLoader","EventTarget","importSpecFile","suite","path","url","join","dispatchEvent","MessageEvent","data","import","loadTree","query","subqueriesToExpand","tree","map","s","q","level","loadCases","iterateLeaves","DefaultTestFileLoader","listing"],"sources":["../../../src/common/internal/file_loader.ts"],"sourcesContent":["import { IterableTestGroup } from '../internal/test_group.js';\nimport { assert } from '../util/util.js';\n\nimport { parseQuery } from './query/parseQuery.js';\nimport { TestQuery } from './query/query.js';\nimport { TestSuiteListing } from './test_suite_listing.js';\nimport { loadTreeForQuery, TestTree, TestTreeLeaf } from './tree.js';\n\n// A listing file, e.g. either of:\n// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>)\n// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing)\ninterface ListingFile {\n listing: Promise<TestSuiteListing> | TestSuiteListing;\n}\n\n// A .spec.ts file, as imported.\nexport interface SpecFile {\n readonly description: string;\n readonly g: IterableTestGroup;\n}\n\nexport interface ImportInfo {\n url: string;\n}\n\ninterface TestFileLoaderEventMap {\n import: MessageEvent<ImportInfo>;\n finish: MessageEvent<void>;\n}\n\nexport interface TestFileLoader extends EventTarget {\n addEventListener<K extends keyof TestFileLoaderEventMap>(\n type: K,\n listener: (this: TestFileLoader, ev: TestFileLoaderEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void;\n removeEventListener<K extends keyof TestFileLoaderEventMap>(\n type: K,\n listener: (this: TestFileLoader, ev: TestFileLoaderEventMap[K]) => void,\n options?: boolean | EventListenerOptions\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions\n ): void;\n}\n\n// Base class for DefaultTestFileLoader and FakeTestFileLoader.\nexport abstract class TestFileLoader extends EventTarget {\n abstract listing(suite: string): Promise<TestSuiteListing>;\n protected abstract import(path: string): Promise<SpecFile>;\n\n importSpecFile(suite: string, path: string[]): Promise<SpecFile> {\n const url = `${suite}/${path.join('/')}.spec.js`;\n this.dispatchEvent(\n new MessageEvent<ImportInfo>('import', { data: { url } })\n );\n return this.import(url);\n }\n\n async loadTree(query: TestQuery, subqueriesToExpand: string[] = []): Promise<TestTree> {\n const tree = await loadTreeForQuery(\n this,\n query,\n subqueriesToExpand.map(s => {\n const q = parseQuery(s);\n assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\\n ${q}`);\n return q;\n })\n );\n this.dispatchEvent(new MessageEvent<void>('finish'));\n return tree;\n }\n\n async loadCases(query: TestQuery): Promise<IterableIterator<TestTreeLeaf>> {\n const tree = await this.loadTree(query);\n return tree.iterateLeaves();\n }\n}\n\nexport class DefaultTestFileLoader extends TestFileLoader {\n async listing(suite: string): Promise<TestSuiteListing> {\n return ((await import(`../../${suite}/listing.js`)) as ListingFile).listing;\n }\n\n import(path: string): Promise<SpecFile> {\n return import(`../../${path}`);\n }\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,QAAQ,iBAAiB;AAExC,SAASC,UAAU,QAAQ,uBAAuB;;;AAGlD,SAASC,gBAAgB,QAAgC,WAAW;;AAEpE;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA;AACA,OAAO,MAAeC,cAAc,SAASC,WAAW,CAAC;;;;EAIvDC,cAAc,CAACC,KAAa,EAAEC,IAAc,EAAqB;IAC/D,MAAMC,GAAG,GAAI,GAAEF,KAAM,IAAGC,IAAI,CAACE,IAAI,CAAC,GAAG,CAAE,UAAS;IAChD,IAAI,CAACC,aAAa;IAChB,IAAIC,YAAY,CAAa,QAAQ,EAAE,EAAEC,IAAI,EAAE,EAAEJ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAC1D;;IACD,OAAO,IAAI,CAACK,MAAM,CAACL,GAAG,CAAC;EACzB;;EAEA,MAAMM,QAAQ,CAACC,KAAgB,EAAEC,kBAA4B,GAAG,EAAE,EAAqB;IACrF,MAAMC,IAAI,GAAG,MAAMf,gBAAgB;IACjC,IAAI;IACJa,KAAK;IACLC,kBAAkB,CAACE,GAAG,CAAC,CAAAC,CAAC,KAAI;MAC1B,MAAMC,CAAC,GAAGnB,UAAU,CAACkB,CAAC,CAAC;MACvBnB,MAAM,CAACoB,CAAC,CAACC,KAAK,IAAI,CAAC,EAAE,MAAO,2DAA0DD,CAAE,EAAC,CAAC;MAC1F,OAAOA,CAAC;IACV,CAAC,CAAC,CACH;;IACD,IAAI,CAACV,aAAa,CAAC,IAAIC,YAAY,CAAO,QAAQ,CAAC,CAAC;IACpD,OAAOM,IAAI;EACb;;EAEA,MAAMK,SAAS,CAACP,KAAgB,EAA2C;IACzE,MAAME,IAAI,GAAG,MAAM,IAAI,CAACH,QAAQ,CAACC,KAAK,CAAC;IACvC,OAAOE,IAAI,CAACM,aAAa,EAAE;EAC7B;AACF;;AAEA,OAAO,MAAMC,qBAAqB,SAASrB,cAAc,CAAC;EACxD,MAAMsB,OAAO,CAACnB,KAAa,EAA6B;IACtD,OAAO,CAAE,MAAM,MAAM,CAAE,SAAQA,KAAM,aAAY,CAAC,EAAkBmB,OAAO;EAC7E;;EAEAZ,MAAM,CAACN,IAAY,EAAqB;IACtC,OAAO,MAAM,CAAE,SAAQA,IAAK,EAAC,CAAC;EAChC;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js
new file mode 100644
index 0000000000..0414e45def
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js
@@ -0,0 +1,45 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { extractImportantStackTrace } from '../stack.js';
+export class LogMessageWithStack extends Error {
+
+
+ stackHiddenMessage = undefined;
+
+ constructor(name, ex) {
+ super(ex.message);
+
+ this.name = name;
+ this.stack = ex.stack;
+ if ('extra' in ex) {
+ this.extra = ex.extra;
+ }
+ }
+
+ /** Set a flag so the stack is not printed in toJSON(). */
+ setStackHidden(stackHiddenMessage) {
+ this.stackHiddenMessage ??= stackHiddenMessage;
+ }
+
+ toJSON() {
+ let m = this.name;
+ if (this.message) m += ': ' + this.message;
+ if (this.stack) {
+ if (this.stackHiddenMessage === undefined) {
+ m += '\n' + extractImportantStackTrace(this);
+ } else if (this.stackHiddenMessage) {
+ m += `\n at (elided: ${this.stackHiddenMessage})`;
+ }
+ }
+ return m;
+ }
+}
+
+/**
+ * Returns a string, nicely indented, for debug logs.
+ * This is used in the cmdline and wpt runtimes. In WPT, it shows up in the `*-actual.txt` file.
+ */
+export function prettyPrintLog(log) {
+ return ' - ' + log.toJSON().replace(/\n/g, '\n ');
+}
+//# sourceMappingURL=log_message.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map
new file mode 100644
index 0000000000..2af81c7452
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"log_message.js","names":["extractImportantStackTrace","LogMessageWithStack","Error","stackHiddenMessage","undefined","constructor","name","ex","message","stack","extra","setStackHidden","toJSON","m","prettyPrintLog","log","replace"],"sources":["../../../../src/common/internal/logging/log_message.ts"],"sourcesContent":["import { ErrorWithExtra } from '../../util/util.js';\nimport { extractImportantStackTrace } from '../stack.js';\n\nexport class LogMessageWithStack extends Error {\n readonly extra: unknown;\n\n private stackHiddenMessage: string | undefined = undefined;\n\n constructor(name: string, ex: Error | ErrorWithExtra) {\n super(ex.message);\n\n this.name = name;\n this.stack = ex.stack;\n if ('extra' in ex) {\n this.extra = ex.extra;\n }\n }\n\n /** Set a flag so the stack is not printed in toJSON(). */\n setStackHidden(stackHiddenMessage: string) {\n this.stackHiddenMessage ??= stackHiddenMessage;\n }\n\n toJSON(): string {\n let m = this.name;\n if (this.message) m += ': ' + this.message;\n if (this.stack) {\n if (this.stackHiddenMessage === undefined) {\n m += '\\n' + extractImportantStackTrace(this);\n } else if (this.stackHiddenMessage) {\n m += `\\n at (elided: ${this.stackHiddenMessage})`;\n }\n }\n return m;\n }\n}\n\n/**\n * Returns a string, nicely indented, for debug logs.\n * This is used in the cmdline and wpt runtimes. In WPT, it shows up in the `*-actual.txt` file.\n */\nexport function prettyPrintLog(log: LogMessageWithStack): string {\n return ' - ' + log.toJSON().replace(/\\n/g, '\\n ');\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,0BAA0B,QAAQ,aAAa;AAExD,OAAO,MAAMC,mBAAmB,SAASC,KAAK,CAAC;;;EAGrCC,kBAAkB,GAAuBC,SAAS;;EAE1DC,WAAW,CAACC,IAAY,EAAEC,EAA0B,EAAE;IACpD,KAAK,CAACA,EAAE,CAACC,OAAO,CAAC;;IAEjB,IAAI,CAACF,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACG,KAAK,GAAGF,EAAE,CAACE,KAAK;IACrB,IAAI,OAAO,IAAIF,EAAE,EAAE;MACjB,IAAI,CAACG,KAAK,GAAGH,EAAE,CAACG,KAAK;IACvB;EACF;;EAEA;EACAC,cAAc,CAACR,kBAA0B,EAAE;IACzC,IAAI,CAACA,kBAAkB,KAAKA,kBAAkB;EAChD;;EAEAS,MAAM,GAAW;IACf,IAAIC,CAAC,GAAG,IAAI,CAACP,IAAI;IACjB,IAAI,IAAI,CAACE,OAAO,EAAEK,CAAC,IAAI,IAAI,GAAG,IAAI,CAACL,OAAO;IAC1C,IAAI,IAAI,CAACC,KAAK,EAAE;MACd,IAAI,IAAI,CAACN,kBAAkB,KAAKC,SAAS,EAAE;QACzCS,CAAC,IAAI,IAAI,GAAGb,0BAA0B,CAAC,IAAI,CAAC;MAC9C,CAAC,MAAM,IAAI,IAAI,CAACG,kBAAkB,EAAE;QAClCU,CAAC,IAAK,mBAAkB,IAAI,CAACV,kBAAmB,GAAE;MACpD;IACF;IACA,OAAOU,CAAC;EACV;AACF;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAc,CAACC,GAAwB,EAAU;EAC/D,OAAO,MAAM,GAAGA,GAAG,CAACH,MAAM,EAAE,CAACI,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC;AACvD"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js
new file mode 100644
index 0000000000..c197579d4a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js
@@ -0,0 +1,31 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { version } from '../version.js';
+import { TestCaseRecorder } from './test_case_recorder.js';
+
+
+
+export class Logger {
+ static globalDebugMode = false;
+
+
+ results = new Map();
+
+ constructor({ overrideDebugMode } = {}) {
+ this.overriddenDebugMode = overrideDebugMode;
+ }
+
+ record(name) {
+ const result = { status: 'running', timems: -1 };
+ this.results.set(name, result);
+ return [
+ new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode),
+ result];
+
+ }
+
+ asJSON(space) {
+ return JSON.stringify({ version, results: Array.from(this.results) }, undefined, space);
+ }
+}
+//# sourceMappingURL=logger.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map
new file mode 100644
index 0000000000..185f17edef
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"logger.js","names":["version","TestCaseRecorder","Logger","globalDebugMode","results","Map","constructor","overrideDebugMode","overriddenDebugMode","record","name","result","status","timems","set","asJSON","space","JSON","stringify","Array","from","undefined"],"sources":["../../../../src/common/internal/logging/logger.ts"],"sourcesContent":["import { version } from '../version.js';\n\nimport { LiveTestCaseResult } from './result.js';\nimport { TestCaseRecorder } from './test_case_recorder.js';\n\nexport type LogResults = Map<string, LiveTestCaseResult>;\n\nexport class Logger {\n static globalDebugMode: boolean = false;\n\n readonly overriddenDebugMode: boolean | undefined;\n readonly results: LogResults = new Map();\n\n constructor({ overrideDebugMode }: { overrideDebugMode?: boolean } = {}) {\n this.overriddenDebugMode = overrideDebugMode;\n }\n\n record(name: string): [TestCaseRecorder, LiveTestCaseResult] {\n const result: LiveTestCaseResult = { status: 'running', timems: -1 };\n this.results.set(name, result);\n return [\n new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode),\n result,\n ];\n }\n\n asJSON(space?: number): string {\n return JSON.stringify({ version, results: Array.from(this.results) }, undefined, space);\n }\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,OAAO,QAAQ,eAAe;AAGvC,SAASC,gBAAgB,QAAQ,yBAAyB;;;;AAI1D,OAAO,MAAMC,MAAM,CAAC;EAClB,OAAOC,eAAe,GAAY,KAAK;;;EAG9BC,OAAO,GAAe,IAAIC,GAAG,EAAE;;EAExCC,WAAW,CAAC,EAAEC,iBAAiB,CAAkC,CAAC,GAAG,CAAC,CAAC,EAAE;IACvE,IAAI,CAACC,mBAAmB,GAAGD,iBAAiB;EAC9C;;EAEAE,MAAM,CAACC,IAAY,EAA0C;IAC3D,MAAMC,MAA0B,GAAG,EAAEC,MAAM,EAAE,SAAS,EAAEC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,CAACT,OAAO,CAACU,GAAG,CAACJ,IAAI,EAAEC,MAAM,CAAC;IAC9B,OAAO;IACL,IAAIV,gBAAgB,CAACU,MAAM,EAAE,IAAI,CAACH,mBAAmB,IAAIN,MAAM,CAACC,eAAe,CAAC;IAChFQ,MAAM,CACP;;EACH;;EAEAI,MAAM,CAACC,KAAc,EAAU;IAC7B,OAAOC,IAAI,CAACC,SAAS,CAAC,EAAElB,OAAO,EAAEI,OAAO,EAAEe,KAAK,CAACC,IAAI,CAAC,IAAI,CAAChB,OAAO,CAAC,CAAC,CAAC,EAAEiB,SAAS,EAAEL,KAAK,CAAC;EACzF;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js
new file mode 100644
index 0000000000..bbf217be6f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js
@@ -0,0 +1,4 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/export {};
+//# sourceMappingURL=result.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map
new file mode 100644
index 0000000000..091c7cba8c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"result.js","names":[],"sources":["../../../../src/common/internal/logging/result.ts"],"sourcesContent":["import { LogMessageWithStack } from './log_message.js';\n\n// MAINTENANCE_TODO: Add warn expectations\nexport type Expectation = 'pass' | 'skip' | 'fail';\n\nexport type Status = 'running' | 'warn' | Expectation;\n\nexport interface TestCaseResult {\n status: Status;\n timems: number;\n}\n\nexport interface LiveTestCaseResult extends TestCaseResult {\n logs?: LogMessageWithStack[];\n}\n\nexport interface TransferredTestCaseResult extends TestCaseResult {\n // When transferred from a worker, a LogMessageWithStack turns into a generic Error\n // (its prototype gets lost and replaced with Error).\n logs?: Error[];\n}\n"],"mappings":";AAAA;AAAA,G"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js
new file mode 100644
index 0000000000..85ea61d862
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js
@@ -0,0 +1,159 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { SkipTestCase, UnexpectedPassError } from '../../framework/fixture.js';import { globalTestConfig } from '../../framework/test_config.js';import { now, assert } from '../../util/util.js';
+
+import { LogMessageWithStack } from './log_message.js';var
+
+
+LogSeverity;(function (LogSeverity) {LogSeverity[LogSeverity["Pass"] = 0] = "Pass";LogSeverity[LogSeverity["Skip"] = 1] = "Skip";LogSeverity[LogSeverity["Warn"] = 2] = "Warn";LogSeverity[LogSeverity["ExpectFailed"] = 3] = "ExpectFailed";LogSeverity[LogSeverity["ValidationFailed"] = 4] = "ValidationFailed";LogSeverity[LogSeverity["ThrewException"] = 5] = "ThrewException";})(LogSeverity || (LogSeverity = {}));
+
+
+
+
+
+
+
+
+const kMaxLogStacks = 2;
+const kMinSeverityForStack = LogSeverity.Warn;
+
+/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */
+export class TestCaseRecorder {
+
+ inSubCase = false;
+ subCaseStatus = LogSeverity.Pass;
+ finalCaseStatus = LogSeverity.Pass;
+ hideStacksBelowSeverity = kMinSeverityForStack;
+ startTime = -1;
+ logs = [];
+ logLinesAtCurrentSeverity = 0;
+ debugging = false;
+ /** Used to dedup log messages which have identical stacks. */
+ messagesForPreviouslySeenStacks = new Map();
+
+ constructor(result, debugging) {
+ this.result = result;
+ this.debugging = debugging;
+ }
+
+ start() {
+ assert(this.startTime < 0, 'TestCaseRecorder cannot be reused');
+ this.startTime = now();
+ }
+
+ finish() {
+ assert(this.startTime >= 0, 'finish() before start()');
+
+ const timeMilliseconds = now() - this.startTime;
+ // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.
+ this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000;
+
+ // Convert numeric enum back to string (but expose 'exception' as 'fail')
+ this.result.status =
+ this.finalCaseStatus === LogSeverity.Pass ?
+ 'pass' :
+ this.finalCaseStatus === LogSeverity.Skip ?
+ 'skip' :
+ this.finalCaseStatus === LogSeverity.Warn ?
+ 'warn' :
+ 'fail'; // Everything else is an error
+
+ this.result.logs = this.logs;
+ }
+
+ beginSubCase() {
+ this.subCaseStatus = LogSeverity.Pass;
+ this.inSubCase = true;
+ }
+
+ endSubCase(expectedStatus) {
+ try {
+ if (expectedStatus === 'fail') {
+ if (this.subCaseStatus <= LogSeverity.Warn) {
+ throw new UnexpectedPassError();
+ } else {
+ this.subCaseStatus = LogSeverity.Pass;
+ }
+ }
+ } finally {
+ this.inSubCase = false;
+ if (this.subCaseStatus > this.finalCaseStatus) {
+ this.finalCaseStatus = this.subCaseStatus;
+ }
+ }
+ }
+
+ injectResult(injectedResult) {
+ Object.assign(this.result, injectedResult);
+ }
+
+ debug(ex) {
+ if (!this.debugging) return;
+ this.logImpl(LogSeverity.Pass, 'DEBUG', ex);
+ }
+
+ info(ex) {
+ this.logImpl(LogSeverity.Pass, 'INFO', ex);
+ }
+
+ skipped(ex) {
+ this.logImpl(LogSeverity.Skip, 'SKIP', ex);
+ }
+
+ warn(ex) {
+ this.logImpl(LogSeverity.Warn, 'WARN', ex);
+ }
+
+ expectationFailed(ex) {
+ this.logImpl(LogSeverity.ExpectFailed, 'EXPECTATION FAILED', ex);
+ }
+
+ validationFailed(ex) {
+ this.logImpl(LogSeverity.ValidationFailed, 'VALIDATION FAILED', ex);
+ }
+
+ threw(ex) {
+ if (ex instanceof SkipTestCase) {
+ this.skipped(ex);
+ return;
+ }
+ this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex);
+ }
+
+ logImpl(level, name, baseException) {
+ assert(baseException instanceof Error, 'test threw a non-Error object');
+ globalTestConfig.testHeartbeatCallback();
+ const logMessage = new LogMessageWithStack(name, baseException);
+
+ // Final case status should be the "worst" of all log entries.
+ if (this.inSubCase) {
+ if (level > this.subCaseStatus) this.subCaseStatus = level;
+ } else {
+ if (level > this.finalCaseStatus) this.finalCaseStatus = level;
+ }
+
+ // setFirstLineOnly for all logs except `kMaxLogStacks` stacks at the highest severity
+ if (level > this.hideStacksBelowSeverity) {
+ this.logLinesAtCurrentSeverity = 0;
+ this.hideStacksBelowSeverity = level;
+
+ // Go back and setFirstLineOnly for everything of a lower log level
+ for (const log of this.logs) {
+ log.setStackHidden('below max severity');
+ }
+ }
+ if (level === this.hideStacksBelowSeverity) {
+ this.logLinesAtCurrentSeverity++;
+ } else if (level < kMinSeverityForStack) {
+ logMessage.setStackHidden('');
+ } else if (level < this.hideStacksBelowSeverity) {
+ logMessage.setStackHidden('below max severity');
+ }
+ if (this.logLinesAtCurrentSeverity > kMaxLogStacks) {
+ logMessage.setStackHidden(`only ${kMaxLogStacks} shown`);
+ }
+
+ this.logs.push(logMessage);
+ }
+}
+//# sourceMappingURL=test_case_recorder.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map
new file mode 100644
index 0000000000..06c2e79bcd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"test_case_recorder.js","names":["SkipTestCase","UnexpectedPassError","globalTestConfig","now","assert","LogMessageWithStack","LogSeverity","kMaxLogStacks","kMinSeverityForStack","Warn","TestCaseRecorder","inSubCase","subCaseStatus","Pass","finalCaseStatus","hideStacksBelowSeverity","startTime","logs","logLinesAtCurrentSeverity","debugging","messagesForPreviouslySeenStacks","Map","constructor","result","start","finish","timeMilliseconds","timems","Math","ceil","status","Skip","beginSubCase","endSubCase","expectedStatus","injectResult","injectedResult","Object","assign","debug","ex","logImpl","info","skipped","warn","expectationFailed","ExpectFailed","validationFailed","ValidationFailed","threw","ThrewException","level","name","baseException","Error","testHeartbeatCallback","logMessage","log","setStackHidden","push"],"sources":["../../../../src/common/internal/logging/test_case_recorder.ts"],"sourcesContent":["import { SkipTestCase, UnexpectedPassError } from '../../framework/fixture.js';\nimport { globalTestConfig } from '../../framework/test_config.js';\nimport { now, assert } from '../../util/util.js';\n\nimport { LogMessageWithStack } from './log_message.js';\nimport { Expectation, LiveTestCaseResult } from './result.js';\n\nenum LogSeverity {\n Pass = 0,\n Skip = 1,\n Warn = 2,\n ExpectFailed = 3,\n ValidationFailed = 4,\n ThrewException = 5,\n}\n\nconst kMaxLogStacks = 2;\nconst kMinSeverityForStack = LogSeverity.Warn;\n\n/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */\nexport class TestCaseRecorder {\n private result: LiveTestCaseResult;\n private inSubCase: boolean = false;\n private subCaseStatus = LogSeverity.Pass;\n private finalCaseStatus = LogSeverity.Pass;\n private hideStacksBelowSeverity = kMinSeverityForStack;\n private startTime = -1;\n private logs: LogMessageWithStack[] = [];\n private logLinesAtCurrentSeverity = 0;\n private debugging = false;\n /** Used to dedup log messages which have identical stacks. */\n private messagesForPreviouslySeenStacks = new Map<string, LogMessageWithStack>();\n\n constructor(result: LiveTestCaseResult, debugging: boolean) {\n this.result = result;\n this.debugging = debugging;\n }\n\n start(): void {\n assert(this.startTime < 0, 'TestCaseRecorder cannot be reused');\n this.startTime = now();\n }\n\n finish(): void {\n assert(this.startTime >= 0, 'finish() before start()');\n\n const timeMilliseconds = now() - this.startTime;\n // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.\n this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000;\n\n // Convert numeric enum back to string (but expose 'exception' as 'fail')\n this.result.status =\n this.finalCaseStatus === LogSeverity.Pass\n ? 'pass'\n : this.finalCaseStatus === LogSeverity.Skip\n ? 'skip'\n : this.finalCaseStatus === LogSeverity.Warn\n ? 'warn'\n : 'fail'; // Everything else is an error\n\n this.result.logs = this.logs;\n }\n\n beginSubCase() {\n this.subCaseStatus = LogSeverity.Pass;\n this.inSubCase = true;\n }\n\n endSubCase(expectedStatus: Expectation) {\n try {\n if (expectedStatus === 'fail') {\n if (this.subCaseStatus <= LogSeverity.Warn) {\n throw new UnexpectedPassError();\n } else {\n this.subCaseStatus = LogSeverity.Pass;\n }\n }\n } finally {\n this.inSubCase = false;\n if (this.subCaseStatus > this.finalCaseStatus) {\n this.finalCaseStatus = this.subCaseStatus;\n }\n }\n }\n\n injectResult(injectedResult: LiveTestCaseResult): void {\n Object.assign(this.result, injectedResult);\n }\n\n debug(ex: Error): void {\n if (!this.debugging) return;\n this.logImpl(LogSeverity.Pass, 'DEBUG', ex);\n }\n\n info(ex: Error): void {\n this.logImpl(LogSeverity.Pass, 'INFO', ex);\n }\n\n skipped(ex: SkipTestCase): void {\n this.logImpl(LogSeverity.Skip, 'SKIP', ex);\n }\n\n warn(ex: Error): void {\n this.logImpl(LogSeverity.Warn, 'WARN', ex);\n }\n\n expectationFailed(ex: Error): void {\n this.logImpl(LogSeverity.ExpectFailed, 'EXPECTATION FAILED', ex);\n }\n\n validationFailed(ex: Error): void {\n this.logImpl(LogSeverity.ValidationFailed, 'VALIDATION FAILED', ex);\n }\n\n threw(ex: unknown): void {\n if (ex instanceof SkipTestCase) {\n this.skipped(ex);\n return;\n }\n this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex);\n }\n\n private logImpl(level: LogSeverity, name: string, baseException: unknown): void {\n assert(baseException instanceof Error, 'test threw a non-Error object');\n globalTestConfig.testHeartbeatCallback();\n const logMessage = new LogMessageWithStack(name, baseException);\n\n // Final case status should be the \"worst\" of all log entries.\n if (this.inSubCase) {\n if (level > this.subCaseStatus) this.subCaseStatus = level;\n } else {\n if (level > this.finalCaseStatus) this.finalCaseStatus = level;\n }\n\n // setFirstLineOnly for all logs except `kMaxLogStacks` stacks at the highest severity\n if (level > this.hideStacksBelowSeverity) {\n this.logLinesAtCurrentSeverity = 0;\n this.hideStacksBelowSeverity = level;\n\n // Go back and setFirstLineOnly for everything of a lower log level\n for (const log of this.logs) {\n log.setStackHidden('below max severity');\n }\n }\n if (level === this.hideStacksBelowSeverity) {\n this.logLinesAtCurrentSeverity++;\n } else if (level < kMinSeverityForStack) {\n logMessage.setStackHidden('');\n } else if (level < this.hideStacksBelowSeverity) {\n logMessage.setStackHidden('below max severity');\n }\n if (this.logLinesAtCurrentSeverity > kMaxLogStacks) {\n logMessage.setStackHidden(`only ${kMaxLogStacks} shown`);\n }\n\n this.logs.push(logMessage);\n }\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,YAAY,EAAEC,mBAAmB,QAAQ,4BAA4B,CAC9E,SAASC,gBAAgB,QAAQ,gCAAgC,CACjE,SAASC,GAAG,EAAEC,MAAM,QAAQ,oBAAoB;;AAEhD,SAASC,mBAAmB,QAAQ,kBAAkB,CAAC;;;AAGlDC,WAAW,YAAXA,WAAW,GAAXA,WAAW,CAAXA,WAAW,uBAAXA,WAAW,CAAXA,WAAW,uBAAXA,WAAW,CAAXA,WAAW,uBAAXA,WAAW,CAAXA,WAAW,uCAAXA,WAAW,CAAXA,WAAW,+CAAXA,WAAW,CAAXA,WAAW,8CAAXA,WAAW,KAAXA,WAAW;;;;;;;;;AAShB,MAAMC,aAAa,GAAG,CAAC;AACvB,MAAMC,oBAAoB,GAAGF,WAAW,CAACG,IAAI;;AAE7C;AACA,OAAO,MAAMC,gBAAgB,CAAC;;EAEpBC,SAAS,GAAY,KAAK;EAC1BC,aAAa,GAAGN,WAAW,CAACO,IAAI;EAChCC,eAAe,GAAGR,WAAW,CAACO,IAAI;EAClCE,uBAAuB,GAAGP,oBAAoB;EAC9CQ,SAAS,GAAG,CAAC,CAAC;EACdC,IAAI,GAA0B,EAAE;EAChCC,yBAAyB,GAAG,CAAC;EAC7BC,SAAS,GAAG,KAAK;EACzB;EACQC,+BAA+B,GAAG,IAAIC,GAAG,EAA+B;;EAEhFC,WAAW,CAACC,MAA0B,EAAEJ,SAAkB,EAAE;IAC1D,IAAI,CAACI,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACJ,SAAS,GAAGA,SAAS;EAC5B;;EAEAK,KAAK,GAAS;IACZpB,MAAM,CAAC,IAAI,CAACY,SAAS,GAAG,CAAC,EAAE,mCAAmC,CAAC;IAC/D,IAAI,CAACA,SAAS,GAAGb,GAAG,EAAE;EACxB;;EAEAsB,MAAM,GAAS;IACbrB,MAAM,CAAC,IAAI,CAACY,SAAS,IAAI,CAAC,EAAE,yBAAyB,CAAC;;IAEtD,MAAMU,gBAAgB,GAAGvB,GAAG,EAAE,GAAG,IAAI,CAACa,SAAS;IAC/C;IACA,IAAI,CAACO,MAAM,CAACI,MAAM,GAAGC,IAAI,CAACC,IAAI,CAACH,gBAAgB,GAAG,IAAI,CAAC,GAAG,IAAI;;IAE9D;IACA,IAAI,CAACH,MAAM,CAACO,MAAM;IAChB,IAAI,CAAChB,eAAe,KAAKR,WAAW,CAACO,IAAI;IACrC,MAAM;IACN,IAAI,CAACC,eAAe,KAAKR,WAAW,CAACyB,IAAI;IACzC,MAAM;IACN,IAAI,CAACjB,eAAe,KAAKR,WAAW,CAACG,IAAI;IACzC,MAAM;IACN,MAAM,CAAC,CAAC;;IAEd,IAAI,CAACc,MAAM,CAACN,IAAI,GAAG,IAAI,CAACA,IAAI;EAC9B;;EAEAe,YAAY,GAAG;IACb,IAAI,CAACpB,aAAa,GAAGN,WAAW,CAACO,IAAI;IACrC,IAAI,CAACF,SAAS,GAAG,IAAI;EACvB;;EAEAsB,UAAU,CAACC,cAA2B,EAAE;IACtC,IAAI;MACF,IAAIA,cAAc,KAAK,MAAM,EAAE;QAC7B,IAAI,IAAI,CAACtB,aAAa,IAAIN,WAAW,CAACG,IAAI,EAAE;UAC1C,MAAM,IAAIR,mBAAmB,EAAE;QACjC,CAAC,MAAM;UACL,IAAI,CAACW,aAAa,GAAGN,WAAW,CAACO,IAAI;QACvC;MACF;IACF,CAAC,SAAS;MACR,IAAI,CAACF,SAAS,GAAG,KAAK;MACtB,IAAI,IAAI,CAACC,aAAa,GAAG,IAAI,CAACE,eAAe,EAAE;QAC7C,IAAI,CAACA,eAAe,GAAG,IAAI,CAACF,aAAa;MAC3C;IACF;EACF;;EAEAuB,YAAY,CAACC,cAAkC,EAAQ;IACrDC,MAAM,CAACC,MAAM,CAAC,IAAI,CAACf,MAAM,EAAEa,cAAc,CAAC;EAC5C;;EAEAG,KAAK,CAACC,EAAS,EAAQ;IACrB,IAAI,CAAC,IAAI,CAACrB,SAAS,EAAE;IACrB,IAAI,CAACsB,OAAO,CAACnC,WAAW,CAACO,IAAI,EAAE,OAAO,EAAE2B,EAAE,CAAC;EAC7C;;EAEAE,IAAI,CAACF,EAAS,EAAQ;IACpB,IAAI,CAACC,OAAO,CAACnC,WAAW,CAACO,IAAI,EAAE,MAAM,EAAE2B,EAAE,CAAC;EAC5C;;EAEAG,OAAO,CAACH,EAAgB,EAAQ;IAC9B,IAAI,CAACC,OAAO,CAACnC,WAAW,CAACyB,IAAI,EAAE,MAAM,EAAES,EAAE,CAAC;EAC5C;;EAEAI,IAAI,CAACJ,EAAS,EAAQ;IACpB,IAAI,CAACC,OAAO,CAACnC,WAAW,CAACG,IAAI,EAAE,MAAM,EAAE+B,EAAE,CAAC;EAC5C;;EAEAK,iBAAiB,CAACL,EAAS,EAAQ;IACjC,IAAI,CAACC,OAAO,CAACnC,WAAW,CAACwC,YAAY,EAAE,oBAAoB,EAAEN,EAAE,CAAC;EAClE;;EAEAO,gBAAgB,CAACP,EAAS,EAAQ;IAChC,IAAI,CAACC,OAAO,CAACnC,WAAW,CAAC0C,gBAAgB,EAAE,mBAAmB,EAAER,EAAE,CAAC;EACrE;;EAEAS,KAAK,CAACT,EAAW,EAAQ;IACvB,IAAIA,EAAE,YAAYxC,YAAY,EAAE;MAC9B,IAAI,CAAC2C,OAAO,CAACH,EAAE,CAAC;MAChB;IACF;IACA,IAAI,CAACC,OAAO,CAACnC,WAAW,CAAC4C,cAAc,EAAE,WAAW,EAAEV,EAAE,CAAC;EAC3D;;EAEQC,OAAO,CAACU,KAAkB,EAAEC,IAAY,EAAEC,aAAsB,EAAQ;IAC9EjD,MAAM,CAACiD,aAAa,YAAYC,KAAK,EAAE,+BAA+B,CAAC;IACvEpD,gBAAgB,CAACqD,qBAAqB,EAAE;IACxC,MAAMC,UAAU,GAAG,IAAInD,mBAAmB,CAAC+C,IAAI,EAAEC,aAAa,CAAC;;IAE/D;IACA,IAAI,IAAI,CAAC1C,SAAS,EAAE;MAClB,IAAIwC,KAAK,GAAG,IAAI,CAACvC,aAAa,EAAE,IAAI,CAACA,aAAa,GAAGuC,KAAK;IAC5D,CAAC,MAAM;MACL,IAAIA,KAAK,GAAG,IAAI,CAACrC,eAAe,EAAE,IAAI,CAACA,eAAe,GAAGqC,KAAK;IAChE;;IAEA;IACA,IAAIA,KAAK,GAAG,IAAI,CAACpC,uBAAuB,EAAE;MACxC,IAAI,CAACG,yBAAyB,GAAG,CAAC;MAClC,IAAI,CAACH,uBAAuB,GAAGoC,KAAK;;MAEpC;MACA,KAAK,MAAMM,GAAG,IAAI,IAAI,CAACxC,IAAI,EAAE;QAC3BwC,GAAG,CAACC,cAAc,CAAC,oBAAoB,CAAC;MAC1C;IACF;IACA,IAAIP,KAAK,KAAK,IAAI,CAACpC,uBAAuB,EAAE;MAC1C,IAAI,CAACG,yBAAyB,EAAE;IAClC,CAAC,MAAM,IAAIiC,KAAK,GAAG3C,oBAAoB,EAAE;MACvCgD,UAAU,CAACE,cAAc,CAAC,EAAE,CAAC;IAC/B,CAAC,MAAM,IAAIP,KAAK,GAAG,IAAI,CAACpC,uBAAuB,EAAE;MAC/CyC,UAAU,CAACE,cAAc,CAAC,oBAAoB,CAAC;IACjD;IACA,IAAI,IAAI,CAACxC,yBAAyB,GAAGX,aAAa,EAAE;MAClDiD,UAAU,CAACE,cAAc,CAAE,QAAOnD,aAAc,QAAO,CAAC;IAC1D;;IAEA,IAAI,CAACU,IAAI,CAAC0C,IAAI,CAACH,UAAU,CAAC;EAC5B;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js
new file mode 100644
index 0000000000..d1ba896d90
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js
@@ -0,0 +1,125 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from '../util/util.js';
+
+import { comparePublicParamsPaths, Ordering } from './query/compare.js';
+import { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+export function paramKeyIsPublic(key) {
+ return !key.startsWith('_');
+}
+
+export function extractPublicParams(params) {
+ const publicParams = {};
+ for (const k of Object.keys(params)) {
+ if (paramKeyIsPublic(k)) {
+ publicParams[k] = params[k];
+ }
+ }
+ return publicParams;
+}
+
+export const badParamValueChars = new RegExp(
+'[' + kParamKVSeparator + kParamSeparator + kWildcard + ']');
+
+
+export function publicParamsEquals(x, y) {
+ return comparePublicParamsPaths(x, y) === Ordering.Equal;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+function typeAssert() {}
+{
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ typeAssert();
+ typeAssert();
+ typeAssert();
+ typeAssert();
+ typeAssert();
+
+ typeAssert();
+
+ typeAssert();
+ typeAssert();
+ typeAssert();
+ typeAssert();
+ typeAssert();
+
+ // Unexpected test results - hopefully okay to ignore these
+ typeAssert();
+ typeAssert();
+ }
+}
+
+
+
+
+
+
+export function mergeParams(a, b) {
+ for (const key of Object.keys(a)) {
+ assert(!(key in b), 'Duplicate key: ' + key);
+ }
+ return { ...a, ...b };
+}
+//# sourceMappingURL=params_utils.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map
new file mode 100644
index 0000000000..eb03517c23
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"params_utils.js","names":["assert","comparePublicParamsPaths","Ordering","kWildcard","kParamSeparator","kParamKVSeparator","paramKeyIsPublic","key","startsWith","extractPublicParams","params","publicParams","k","Object","keys","badParamValueChars","RegExp","publicParamsEquals","x","y","Equal","typeAssert","mergeParams","a","b"],"sources":["../../../src/common/internal/params_utils.ts"],"sourcesContent":["import { TestParams } from '../framework/fixture.js';\nimport { ResolveType, UnionToIntersection } from '../util/types.js';\nimport { assert } from '../util/util.js';\n\nimport { comparePublicParamsPaths, Ordering } from './query/compare.js';\nimport { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js';\n\nexport type JSONWithUndefined =\n | undefined\n | null\n | number\n | string\n | boolean\n | readonly JSONWithUndefined[]\n // Ideally this would recurse into JSONWithUndefined, but it breaks code.\n | { readonly [k: string]: unknown };\nexport interface TestParamsRW {\n [k: string]: JSONWithUndefined;\n}\nexport type TestParamsIterable = Iterable<TestParams>;\n\nexport function paramKeyIsPublic(key: string): boolean {\n return !key.startsWith('_');\n}\n\nexport function extractPublicParams(params: TestParams): TestParams {\n const publicParams: TestParamsRW = {};\n for (const k of Object.keys(params)) {\n if (paramKeyIsPublic(k)) {\n publicParams[k] = params[k];\n }\n }\n return publicParams;\n}\n\nexport const badParamValueChars = new RegExp(\n '[' + kParamKVSeparator + kParamSeparator + kWildcard + ']'\n);\n\nexport function publicParamsEquals(x: TestParams, y: TestParams): boolean {\n return comparePublicParamsPaths(x, y) === Ordering.Equal;\n}\n\nexport type KeyOfNeverable<T> = T extends never ? never : keyof T;\nexport type AllKeysFromUnion<T> = keyof T | KeyOfNeverable<UnionToIntersection<T>>;\nexport type KeyOfOr<T, K, Default> = K extends keyof T ? T[K] : Default;\n\n/**\n * Flatten a union of interfaces into a single interface encoding the same type.\n *\n * Flattens a union in such a way that:\n * `{ a: number, b?: undefined } | { b: string, a?: undefined }`\n * (which is the value type of `[{ a: 1 }, { b: 1 }]`)\n * becomes `{ a: number | undefined, b: string | undefined }`.\n *\n * And also works for `{ a: number } | { b: string }` which maps to the same.\n */\nexport type FlattenUnionOfInterfaces<T> = {\n [K in AllKeysFromUnion<T>]: KeyOfOr<\n T,\n // If T always has K, just take T[K] (union of C[K] for each component C of T):\n K,\n // Otherwise, take the union of C[K] for each component C of T, PLUS undefined:\n undefined | KeyOfOr<UnionToIntersection<T>, K, void>\n >;\n};\n\n/* eslint-disable-next-line @typescript-eslint/no-unused-vars */\nfunction typeAssert<T extends 'pass'>() {}\n{\n type Test<T, U> = [T] extends [U]\n ? [U] extends [T]\n ? 'pass'\n : { actual: ResolveType<T>; expected: U }\n : { actual: ResolveType<T>; expected: U };\n\n type T01 = { a: number } | { b: string };\n type T02 = { a: number } | { b?: string };\n type T03 = { a: number } | { a?: number };\n type T04 = { a: number } | { a: string };\n type T05 = { a: number } | { a?: string };\n\n type T11 = { a: number; b?: undefined } | { a?: undefined; b: string };\n\n type T21 = { a: number; b?: undefined } | { b: string };\n type T22 = { a: number; b?: undefined } | { b?: string };\n type T23 = { a: number; b?: undefined } | { a?: number };\n type T24 = { a: number; b?: undefined } | { a: string };\n type T25 = { a: number; b?: undefined } | { a?: string };\n type T26 = { a: number; b?: undefined } | { a: undefined };\n type T27 = { a: number; b?: undefined } | { a: undefined; b: undefined };\n\n /* prettier-ignore */ {\n typeAssert<Test<FlattenUnionOfInterfaces<T01>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T02>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T03>, { a: number | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T04>, { a: number | string }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T05>, { a: number | string | undefined }>>();\n\n typeAssert<Test<FlattenUnionOfInterfaces<T11>, { a: number | undefined; b: string | undefined }>>();\n\n typeAssert<Test<FlattenUnionOfInterfaces<T22>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T23>, { a: number | undefined; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T24>, { a: number | string; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T25>, { a: number | string | undefined; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T27>, { a: number | undefined; b: undefined }>>();\n\n // Unexpected test results - hopefully okay to ignore these\n typeAssert<Test<FlattenUnionOfInterfaces<T21>, { b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T26>, { a: number | undefined }>>();\n }\n}\n\nexport type Merged<A, B> = MergedFromFlat<A, FlattenUnionOfInterfaces<B>>;\nexport type MergedFromFlat<A, B> = {\n [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;\n};\n\nexport function mergeParams<A extends {}, B extends {}>(a: A, b: B): Merged<A, B> {\n for (const key of Object.keys(a)) {\n assert(!(key in b), 'Duplicate key: ' + key);\n }\n return { ...a, ...b } as Merged<A, B>;\n}\n"],"mappings":";AAAA;AAAA,GAEA,SAASA,MAAM,QAAQ,iBAAiB;;AAExC,SAASC,wBAAwB,EAAEC,QAAQ,QAAQ,oBAAoB;AACvE,SAASC,SAAS,EAAEC,eAAe,EAAEC,iBAAiB,QAAQ,uBAAuB;;;;;;;;;;;;;;;;AAgBrF,OAAO,SAASC,gBAAgB,CAACC,GAAW,EAAW;EACrD,OAAO,CAACA,GAAG,CAACC,UAAU,CAAC,GAAG,CAAC;AAC7B;;AAEA,OAAO,SAASC,mBAAmB,CAACC,MAAkB,EAAc;EAClE,MAAMC,YAA0B,GAAG,CAAC,CAAC;EACrC,KAAK,MAAMC,CAAC,IAAIC,MAAM,CAACC,IAAI,CAACJ,MAAM,CAAC,EAAE;IACnC,IAAIJ,gBAAgB,CAACM,CAAC,CAAC,EAAE;MACvBD,YAAY,CAACC,CAAC,CAAC,GAAGF,MAAM,CAACE,CAAC,CAAC;IAC7B;EACF;EACA,OAAOD,YAAY;AACrB;;AAEA,OAAO,MAAMI,kBAAkB,GAAG,IAAIC,MAAM;AAC1C,GAAG,GAAGX,iBAAiB,GAAGD,eAAe,GAAGD,SAAS,GAAG,GAAG,CAC5D;;;AAED,OAAO,SAASc,kBAAkB,CAACC,CAAa,EAAEC,CAAa,EAAW;EACxE,OAAOlB,wBAAwB,CAACiB,CAAC,EAAEC,CAAC,CAAC,KAAKjB,QAAQ,CAACkB,KAAK;AAC1D;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAASC,UAAU,GAAqB,CAAC;AACzC;;;;;;;;;;;;;;;;;;;;;;;EAuBwB;IACpBA,UAAU,EAAyF;IACnGA,UAAU,EAAyF;IACnGA,UAAU,EAAkE;IAC5EA,UAAU,EAA+D;IACzEA,UAAU,EAA2E;;IAErFA,UAAU,EAAyF;;IAEnGA,UAAU,EAAyF;IACnGA,UAAU,EAAgF;IAC1FA,UAAU,EAA6E;IACvFA,UAAU,EAAyF;IACnGA,UAAU,EAAgF;;IAE1F;IACAA,UAAU,EAAkE;IAC5EA,UAAU,EAAkE;EAC9E;AACF;;;;;;;AAOA,OAAO,SAASC,WAAW,CAA6BC,CAAI,EAAEC,CAAI,EAAgB;EAChF,KAAK,MAAMjB,GAAG,IAAIM,MAAM,CAACC,IAAI,CAACS,CAAC,CAAC,EAAE;IAChCvB,MAAM,CAAC,EAAEO,GAAG,IAAIiB,CAAC,CAAC,EAAE,iBAAiB,GAAGjB,GAAG,CAAC;EAC9C;EACA,OAAO,EAAE,GAAGgB,CAAC,EAAE,GAAGC,CAAC,CAAC,CAAC;AACvB"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js
new file mode 100644
index 0000000000..57975be912
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js
@@ -0,0 +1,95 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert, objectEquals } from '../../util/util.js';import { paramKeyIsPublic } from '../params_utils.js';
+
+
+
+export let Ordering;
+
+
+
+
+
+
+/**
+ * Compares two queries for their ordering (which is used to build the tree).
+ *
+ * See src/unittests/query_compare.spec.ts for examples.
+ */(function (Ordering) {Ordering[Ordering["Unordered"] = 0] = "Unordered";Ordering[Ordering["StrictSuperset"] = 1] = "StrictSuperset";Ordering[Ordering["Equal"] = 2] = "Equal";Ordering[Ordering["StrictSubset"] = 3] = "StrictSubset";})(Ordering || (Ordering = {}));
+export function compareQueries(a, b) {
+ if (a.suite !== b.suite) {
+ return Ordering.Unordered;
+ }
+
+ const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts);
+ if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) {
+ return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile);
+ }
+ assert('testPathParts' in a && 'testPathParts' in b);
+
+ const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts);
+ if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) {
+ return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest);
+ }
+ assert('params' in a && 'params' in b);
+
+ const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params);
+ if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) {
+ return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase);
+ }
+ return Ordering.Equal;
+}
+
+/**
+ * Compares a single level of a query.
+ *
+ * "IsBig" means the query is big relative to the level, e.g. for test-level:
+ * - Anything >= `suite:a,*` is big
+ * - Anything <= `suite:a:*` is small
+ */
+function compareOneLevel(ordering, aIsBig, bIsBig) {
+ assert(ordering !== Ordering.Equal || aIsBig || bIsBig);
+ if (ordering === Ordering.Unordered) return Ordering.Unordered;
+ if (aIsBig && bIsBig) return ordering;
+ if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled
+ // Exactly one of (a, b) is big.
+ if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset;
+ if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset;
+ return Ordering.Unordered;
+}
+
+function comparePaths(a, b) {
+ const shorter = Math.min(a.length, b.length);
+
+ for (let i = 0; i < shorter; ++i) {
+ if (a[i] !== b[i]) {
+ return Ordering.Unordered;
+ }
+ }
+ if (a.length === b.length) {
+ return Ordering.Equal;
+ } else if (a.length < b.length) {
+ return Ordering.StrictSuperset;
+ } else {
+ return Ordering.StrictSubset;
+ }
+}
+
+export function comparePublicParamsPaths(a, b) {
+ const aKeys = Object.keys(a).filter((k) => paramKeyIsPublic(k));
+ const commonKeys = new Set(aKeys.filter((k) => k in b));
+
+ for (const k of commonKeys) {
+ if (!objectEquals(a[k], b[k])) {
+ return Ordering.Unordered;
+ }
+ }
+ const bKeys = Object.keys(b).filter((k) => paramKeyIsPublic(k));
+ const aRemainingKeys = aKeys.length - commonKeys.size;
+ const bRemainingKeys = bKeys.length - commonKeys.size;
+ if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal;
+ if (aRemainingKeys === 0) return Ordering.StrictSuperset;
+ if (bRemainingKeys === 0) return Ordering.StrictSubset;
+ return Ordering.Unordered;
+}
+//# sourceMappingURL=compare.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map
new file mode 100644
index 0000000000..d4e90794ff
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"compare.js","names":["assert","objectEquals","paramKeyIsPublic","Ordering","compareQueries","a","b","suite","Unordered","filePathOrdering","comparePaths","filePathParts","Equal","isMultiFile","compareOneLevel","testPathOrdering","testPathParts","isMultiTest","paramsPathOrdering","comparePublicParamsPaths","params","isMultiCase","ordering","aIsBig","bIsBig","StrictSubset","StrictSuperset","shorter","Math","min","length","i","aKeys","Object","keys","filter","k","commonKeys","Set","bKeys","aRemainingKeys","size","bRemainingKeys"],"sources":["../../../../src/common/internal/query/compare.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { assert, objectEquals } from '../../util/util.js';\nimport { paramKeyIsPublic } from '../params_utils.js';\n\nimport { TestQuery } from './query.js';\n\nexport const enum Ordering {\n Unordered,\n StrictSuperset,\n Equal,\n StrictSubset,\n}\n\n/**\n * Compares two queries for their ordering (which is used to build the tree).\n *\n * See src/unittests/query_compare.spec.ts for examples.\n */\nexport function compareQueries(a: TestQuery, b: TestQuery): Ordering {\n if (a.suite !== b.suite) {\n return Ordering.Unordered;\n }\n\n const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts);\n if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) {\n return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile);\n }\n assert('testPathParts' in a && 'testPathParts' in b);\n\n const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts);\n if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) {\n return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest);\n }\n assert('params' in a && 'params' in b);\n\n const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params);\n if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) {\n return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase);\n }\n return Ordering.Equal;\n}\n\n/**\n * Compares a single level of a query.\n *\n * \"IsBig\" means the query is big relative to the level, e.g. for test-level:\n * - Anything >= `suite:a,*` is big\n * - Anything <= `suite:a:*` is small\n */\nfunction compareOneLevel(ordering: Ordering, aIsBig: boolean, bIsBig: boolean): Ordering {\n assert(ordering !== Ordering.Equal || aIsBig || bIsBig);\n if (ordering === Ordering.Unordered) return Ordering.Unordered;\n if (aIsBig && bIsBig) return ordering;\n if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled\n // Exactly one of (a, b) is big.\n if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset;\n if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset;\n return Ordering.Unordered;\n}\n\nfunction comparePaths(a: readonly string[], b: readonly string[]): Ordering {\n const shorter = Math.min(a.length, b.length);\n\n for (let i = 0; i < shorter; ++i) {\n if (a[i] !== b[i]) {\n return Ordering.Unordered;\n }\n }\n if (a.length === b.length) {\n return Ordering.Equal;\n } else if (a.length < b.length) {\n return Ordering.StrictSuperset;\n } else {\n return Ordering.StrictSubset;\n }\n}\n\nexport function comparePublicParamsPaths(a: TestParams, b: TestParams): Ordering {\n const aKeys = Object.keys(a).filter(k => paramKeyIsPublic(k));\n const commonKeys = new Set(aKeys.filter(k => k in b));\n\n for (const k of commonKeys) {\n if (!objectEquals(a[k], b[k])) {\n return Ordering.Unordered;\n }\n }\n const bKeys = Object.keys(b).filter(k => paramKeyIsPublic(k));\n const aRemainingKeys = aKeys.length - commonKeys.size;\n const bRemainingKeys = bKeys.length - commonKeys.size;\n if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal;\n if (aRemainingKeys === 0) return Ordering.StrictSuperset;\n if (bRemainingKeys === 0) return Ordering.StrictSubset;\n return Ordering.Unordered;\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,EAAEC,YAAY,QAAQ,oBAAoB,CACzD,SAASC,gBAAgB,QAAQ,oBAAoB;;;;AAIrD,WAAkBC,QAAQ;;;;;;;AAO1B;AACA;AACA;AACA;AACA,GAJA,WAPkBA,QAAQ,GAARA,QAAQ,CAARA,QAAQ,iCAARA,QAAQ,CAARA,QAAQ,2CAARA,QAAQ,CAARA,QAAQ,yBAARA,QAAQ,CAARA,QAAQ,0CAARA,QAAQ,KAARA,QAAQ;AAY1B,OAAO,SAASC,cAAc,CAACC,CAAY,EAAEC,CAAY,EAAY;EACnE,IAAID,CAAC,CAACE,KAAK,KAAKD,CAAC,CAACC,KAAK,EAAE;IACvB,OAAOJ,QAAQ,CAACK,SAAS;EAC3B;;EAEA,MAAMC,gBAAgB,GAAGC,YAAY,CAACL,CAAC,CAACM,aAAa,EAAEL,CAAC,CAACK,aAAa,CAAC;EACvE,IAAIF,gBAAgB,KAAKN,QAAQ,CAACS,KAAK,IAAIP,CAAC,CAACQ,WAAW,IAAIP,CAAC,CAACO,WAAW,EAAE;IACzE,OAAOC,eAAe,CAACL,gBAAgB,EAAEJ,CAAC,CAACQ,WAAW,EAAEP,CAAC,CAACO,WAAW,CAAC;EACxE;EACAb,MAAM,CAAC,eAAe,IAAIK,CAAC,IAAI,eAAe,IAAIC,CAAC,CAAC;;EAEpD,MAAMS,gBAAgB,GAAGL,YAAY,CAACL,CAAC,CAACW,aAAa,EAAEV,CAAC,CAACU,aAAa,CAAC;EACvE,IAAID,gBAAgB,KAAKZ,QAAQ,CAACS,KAAK,IAAIP,CAAC,CAACY,WAAW,IAAIX,CAAC,CAACW,WAAW,EAAE;IACzE,OAAOH,eAAe,CAACC,gBAAgB,EAAEV,CAAC,CAACY,WAAW,EAAEX,CAAC,CAACW,WAAW,CAAC;EACxE;EACAjB,MAAM,CAAC,QAAQ,IAAIK,CAAC,IAAI,QAAQ,IAAIC,CAAC,CAAC;;EAEtC,MAAMY,kBAAkB,GAAGC,wBAAwB,CAACd,CAAC,CAACe,MAAM,EAAEd,CAAC,CAACc,MAAM,CAAC;EACvE,IAAIF,kBAAkB,KAAKf,QAAQ,CAACS,KAAK,IAAIP,CAAC,CAACgB,WAAW,IAAIf,CAAC,CAACe,WAAW,EAAE;IAC3E,OAAOP,eAAe,CAACI,kBAAkB,EAAEb,CAAC,CAACgB,WAAW,EAAEf,CAAC,CAACe,WAAW,CAAC;EAC1E;EACA,OAAOlB,QAAQ,CAACS,KAAK;AACvB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASE,eAAe,CAACQ,QAAkB,EAAEC,MAAe,EAAEC,MAAe,EAAY;EACvFxB,MAAM,CAACsB,QAAQ,KAAKnB,QAAQ,CAACS,KAAK,IAAIW,MAAM,IAAIC,MAAM,CAAC;EACvD,IAAIF,QAAQ,KAAKnB,QAAQ,CAACK,SAAS,EAAE,OAAOL,QAAQ,CAACK,SAAS;EAC9D,IAAIe,MAAM,IAAIC,MAAM,EAAE,OAAOF,QAAQ;EACrC,IAAI,CAACC,MAAM,IAAI,CAACC,MAAM,EAAE,OAAOrB,QAAQ,CAACK,SAAS,CAAC,CAAC;EACnD;EACA,IAAIe,MAAM,IAAID,QAAQ,KAAKnB,QAAQ,CAACsB,YAAY,EAAE,OAAOtB,QAAQ,CAACuB,cAAc;EAChF,IAAIF,MAAM,IAAIF,QAAQ,KAAKnB,QAAQ,CAACuB,cAAc,EAAE,OAAOvB,QAAQ,CAACsB,YAAY;EAChF,OAAOtB,QAAQ,CAACK,SAAS;AAC3B;;AAEA,SAASE,YAAY,CAACL,CAAoB,EAAEC,CAAoB,EAAY;EAC1E,MAAMqB,OAAO,GAAGC,IAAI,CAACC,GAAG,CAACxB,CAAC,CAACyB,MAAM,EAAExB,CAAC,CAACwB,MAAM,CAAC;;EAE5C,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,OAAO,EAAE,EAAEI,CAAC,EAAE;IAChC,IAAI1B,CAAC,CAAC0B,CAAC,CAAC,KAAKzB,CAAC,CAACyB,CAAC,CAAC,EAAE;MACjB,OAAO5B,QAAQ,CAACK,SAAS;IAC3B;EACF;EACA,IAAIH,CAAC,CAACyB,MAAM,KAAKxB,CAAC,CAACwB,MAAM,EAAE;IACzB,OAAO3B,QAAQ,CAACS,KAAK;EACvB,CAAC,MAAM,IAAIP,CAAC,CAACyB,MAAM,GAAGxB,CAAC,CAACwB,MAAM,EAAE;IAC9B,OAAO3B,QAAQ,CAACuB,cAAc;EAChC,CAAC,MAAM;IACL,OAAOvB,QAAQ,CAACsB,YAAY;EAC9B;AACF;;AAEA,OAAO,SAASN,wBAAwB,CAACd,CAAa,EAAEC,CAAa,EAAY;EAC/E,MAAM0B,KAAK,GAAGC,MAAM,CAACC,IAAI,CAAC7B,CAAC,CAAC,CAAC8B,MAAM,CAAC,CAAAC,CAAC,KAAIlC,gBAAgB,CAACkC,CAAC,CAAC,CAAC;EAC7D,MAAMC,UAAU,GAAG,IAAIC,GAAG,CAACN,KAAK,CAACG,MAAM,CAAC,CAAAC,CAAC,KAAIA,CAAC,IAAI9B,CAAC,CAAC,CAAC;;EAErD,KAAK,MAAM8B,CAAC,IAAIC,UAAU,EAAE;IAC1B,IAAI,CAACpC,YAAY,CAACI,CAAC,CAAC+B,CAAC,CAAC,EAAE9B,CAAC,CAAC8B,CAAC,CAAC,CAAC,EAAE;MAC7B,OAAOjC,QAAQ,CAACK,SAAS;IAC3B;EACF;EACA,MAAM+B,KAAK,GAAGN,MAAM,CAACC,IAAI,CAAC5B,CAAC,CAAC,CAAC6B,MAAM,CAAC,CAAAC,CAAC,KAAIlC,gBAAgB,CAACkC,CAAC,CAAC,CAAC;EAC7D,MAAMI,cAAc,GAAGR,KAAK,CAACF,MAAM,GAAGO,UAAU,CAACI,IAAI;EACrD,MAAMC,cAAc,GAAGH,KAAK,CAACT,MAAM,GAAGO,UAAU,CAACI,IAAI;EACrD,IAAID,cAAc,KAAK,CAAC,IAAIE,cAAc,KAAK,CAAC,EAAE,OAAOvC,QAAQ,CAACS,KAAK;EACvE,IAAI4B,cAAc,KAAK,CAAC,EAAE,OAAOrC,QAAQ,CAACuB,cAAc;EACxD,IAAIgB,cAAc,KAAK,CAAC,EAAE,OAAOvC,QAAQ,CAACsB,YAAY;EACtD,OAAOtB,QAAQ,CAACK,SAAS;AAC3B"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js
new file mode 100644
index 0000000000..518ff5ea34
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js
@@ -0,0 +1,24 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /**
+ * Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL.
+ *
+ * `encodeURIComponent` encodes in accordance with `application/x-www-form-urlencoded`,
+ * but URLs don't actually have to be as strict as HTML form encoding
+ * (we interpret this purely from JavaScript).
+ * So we encode the component, then selectively convert some %-encoded escape codes
+ * back to their original form for readability/copyability.
+ */export function encodeURIComponentSelectively(s) {let ret = encodeURIComponent(s);
+ ret = ret.replace(/%22/g, '"'); // for JSON strings
+ ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays
+ ret = ret.replace(/%3A/g, ':'); // for big separator
+ ret = ret.replace(/%3B/g, ';'); // for param separator
+ ret = ret.replace(/%3D/g, '='); // for params (k=v)
+ ret = ret.replace(/%5B/g, '['); // for JSON arrays
+ ret = ret.replace(/%5D/g, ']'); // for JSON arrays
+ ret = ret.replace(/%7B/g, '{'); // for JSON objects
+ ret = ret.replace(/%7D/g, '}'); // for JSON objects
+ ret = ret.replace(/%E2%9C%97/g, '✗'); // for jsUndefinedMagicValue
+ return ret;
+}
+//# sourceMappingURL=encode_selectively.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map
new file mode 100644
index 0000000000..d70d890a32
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"encode_selectively.js","names":["encodeURIComponentSelectively","s","ret","encodeURIComponent","replace"],"sources":["../../../../src/common/internal/query/encode_selectively.ts"],"sourcesContent":["/**\n * Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL.\n *\n * `encodeURIComponent` encodes in accordance with `application/x-www-form-urlencoded`,\n * but URLs don't actually have to be as strict as HTML form encoding\n * (we interpret this purely from JavaScript).\n * So we encode the component, then selectively convert some %-encoded escape codes\n * back to their original form for readability/copyability.\n */\nexport function encodeURIComponentSelectively(s: string): string {\n let ret = encodeURIComponent(s);\n ret = ret.replace(/%22/g, '\"'); // for JSON strings\n ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays\n ret = ret.replace(/%3A/g, ':'); // for big separator\n ret = ret.replace(/%3B/g, ';'); // for param separator\n ret = ret.replace(/%3D/g, '='); // for params (k=v)\n ret = ret.replace(/%5B/g, '['); // for JSON arrays\n ret = ret.replace(/%5D/g, ']'); // for JSON arrays\n ret = ret.replace(/%7B/g, '{'); // for JSON objects\n ret = ret.replace(/%7D/g, '}'); // for JSON objects\n ret = ret.replace(/%E2%9C%97/g, '✗'); // for jsUndefinedMagicValue\n return ret;\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,OAAO,SAASA,6BAA6B,CAACC,CAAS,EAAU,CAC/D,IAAIC,GAAG,GAAGC,kBAAkB,CAACF,CAAC,CAAC;EAC/BC,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC;EACtC,OAAOF,GAAG;AACZ"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js
new file mode 100644
index 0000000000..dc5e20e439
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js
@@ -0,0 +1,84 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert, sortObjectByKey } from '../../util/util.js';
+// JSON can't represent various values and by default stores them as `null`.
+// Instead, storing them as a magic string values in JSON.
+const jsUndefinedMagicValue = '_undef_';
+const jsNaNMagicValue = '_nan_';
+const jsPositiveInfinityMagicValue = '_posinfinity_';
+const jsNegativeInfinityMagicValue = '_neginfinity_';
+
+// -0 needs to be handled separately, because -0 === +0 returns true. Not
+// special casing +0/0, since it behaves intuitively. Assuming that if -0 is
+// being used, the differentiation from +0 is desired.
+const jsNegativeZeroMagicValue = '_negzero_';
+
+const toStringMagicValue = new Map([
+[undefined, jsUndefinedMagicValue],
+[NaN, jsNaNMagicValue],
+[Number.POSITIVE_INFINITY, jsPositiveInfinityMagicValue],
+[Number.NEGATIVE_INFINITY, jsNegativeInfinityMagicValue]
+// No -0 handling because it is special cased.
+]);
+
+const fromStringMagicValue = new Map([
+[jsUndefinedMagicValue, undefined],
+[jsNaNMagicValue, NaN],
+[jsPositiveInfinityMagicValue, Number.POSITIVE_INFINITY],
+[jsNegativeInfinityMagicValue, Number.NEGATIVE_INFINITY],
+// -0 is handled in this direction because there is no comparison issue.
+[jsNegativeZeroMagicValue, -0]]);
+
+
+function stringifyFilter(k, v) {
+ // Make sure no one actually uses a magic value as a parameter.
+ if (typeof v === 'string') {
+ assert(
+ !fromStringMagicValue.has(v),
+ `${v} is a magic value for stringification, so cannot be used`);
+
+
+ assert(
+ v !== jsNegativeZeroMagicValue,
+ `${v} is a magic value for stringification, so cannot be used`);
+
+ }
+
+ if (Object.is(v, -0)) {
+ return jsNegativeZeroMagicValue;
+ }
+
+ return toStringMagicValue.has(v) ? toStringMagicValue.get(v) : v;
+}
+
+export function stringifyParamValue(value) {
+ return JSON.stringify(value, stringifyFilter);
+}
+
+/**
+ * Like stringifyParamValue but sorts dictionaries by key, for hashing.
+ */
+export function stringifyParamValueUniquely(value) {
+ return JSON.stringify(value, (k, v) => {
+ if (typeof v === 'object' && v !== null) {
+ return sortObjectByKey(v);
+ }
+
+ return stringifyFilter(k, v);
+ });
+}
+
+// 'any' is part of the JSON.parse reviver interface, so cannot be avoided.
+
+function parseParamValueReviver(k, v) {
+ if (fromStringMagicValue.has(v)) {
+ return fromStringMagicValue.get(v);
+ }
+
+ return v;
+}
+
+export function parseParamValue(s) {
+ return JSON.parse(s, parseParamValueReviver);
+}
+//# sourceMappingURL=json_param_value.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map
new file mode 100644
index 0000000000..d97066ae17
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"json_param_value.js","names":["assert","sortObjectByKey","jsUndefinedMagicValue","jsNaNMagicValue","jsPositiveInfinityMagicValue","jsNegativeInfinityMagicValue","jsNegativeZeroMagicValue","toStringMagicValue","Map","undefined","NaN","Number","POSITIVE_INFINITY","NEGATIVE_INFINITY","fromStringMagicValue","stringifyFilter","k","v","has","Object","is","get","stringifyParamValue","value","JSON","stringify","stringifyParamValueUniquely","parseParamValueReviver","parseParamValue","s","parse"],"sources":["../../../../src/common/internal/query/json_param_value.ts"],"sourcesContent":["import { assert, sortObjectByKey } from '../../util/util.js';\nimport { JSONWithUndefined } from '../params_utils.js';\n\n// JSON can't represent various values and by default stores them as `null`.\n// Instead, storing them as a magic string values in JSON.\nconst jsUndefinedMagicValue = '_undef_';\nconst jsNaNMagicValue = '_nan_';\nconst jsPositiveInfinityMagicValue = '_posinfinity_';\nconst jsNegativeInfinityMagicValue = '_neginfinity_';\n\n// -0 needs to be handled separately, because -0 === +0 returns true. Not\n// special casing +0/0, since it behaves intuitively. Assuming that if -0 is\n// being used, the differentiation from +0 is desired.\nconst jsNegativeZeroMagicValue = '_negzero_';\n\nconst toStringMagicValue = new Map<unknown, string>([\n [undefined, jsUndefinedMagicValue],\n [NaN, jsNaNMagicValue],\n [Number.POSITIVE_INFINITY, jsPositiveInfinityMagicValue],\n [Number.NEGATIVE_INFINITY, jsNegativeInfinityMagicValue],\n // No -0 handling because it is special cased.\n]);\n\nconst fromStringMagicValue = new Map<string, unknown>([\n [jsUndefinedMagicValue, undefined],\n [jsNaNMagicValue, NaN],\n [jsPositiveInfinityMagicValue, Number.POSITIVE_INFINITY],\n [jsNegativeInfinityMagicValue, Number.NEGATIVE_INFINITY],\n // -0 is handled in this direction because there is no comparison issue.\n [jsNegativeZeroMagicValue, -0],\n]);\n\nfunction stringifyFilter(k: string, v: unknown): unknown {\n // Make sure no one actually uses a magic value as a parameter.\n if (typeof v === 'string') {\n assert(\n !fromStringMagicValue.has(v),\n `${v} is a magic value for stringification, so cannot be used`\n );\n\n assert(\n v !== jsNegativeZeroMagicValue,\n `${v} is a magic value for stringification, so cannot be used`\n );\n }\n\n if (Object.is(v, -0)) {\n return jsNegativeZeroMagicValue;\n }\n\n return toStringMagicValue.has(v) ? toStringMagicValue.get(v) : v;\n}\n\nexport function stringifyParamValue(value: JSONWithUndefined): string {\n return JSON.stringify(value, stringifyFilter);\n}\n\n/**\n * Like stringifyParamValue but sorts dictionaries by key, for hashing.\n */\nexport function stringifyParamValueUniquely(value: JSONWithUndefined): string {\n return JSON.stringify(value, (k, v) => {\n if (typeof v === 'object' && v !== null) {\n return sortObjectByKey(v);\n }\n\n return stringifyFilter(k, v);\n });\n}\n\n// 'any' is part of the JSON.parse reviver interface, so cannot be avoided.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction parseParamValueReviver(k: string, v: any): any {\n if (fromStringMagicValue.has(v)) {\n return fromStringMagicValue.get(v);\n }\n\n return v;\n}\n\nexport function parseParamValue(s: string): JSONWithUndefined {\n return JSON.parse(s, parseParamValueReviver);\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,MAAM,EAAEC,eAAe,QAAQ,oBAAoB;AAG5D;AACA;AACA,MAAMC,qBAAqB,GAAG,SAAS;AACvC,MAAMC,eAAe,GAAG,OAAO;AAC/B,MAAMC,4BAA4B,GAAG,eAAe;AACpD,MAAMC,4BAA4B,GAAG,eAAe;;AAEpD;AACA;AACA;AACA,MAAMC,wBAAwB,GAAG,WAAW;;AAE5C,MAAMC,kBAAkB,GAAG,IAAIC,GAAG,CAAkB;AAClD,CAACC,SAAS,EAAEP,qBAAqB,CAAC;AAClC,CAACQ,GAAG,EAAEP,eAAe,CAAC;AACtB,CAACQ,MAAM,CAACC,iBAAiB,EAAER,4BAA4B,CAAC;AACxD,CAACO,MAAM,CAACE,iBAAiB,EAAER,4BAA4B;AACvD;AAAA,CACD,CAAC;;AAEF,MAAMS,oBAAoB,GAAG,IAAIN,GAAG,CAAkB;AACpD,CAACN,qBAAqB,EAAEO,SAAS,CAAC;AAClC,CAACN,eAAe,EAAEO,GAAG,CAAC;AACtB,CAACN,4BAA4B,EAAEO,MAAM,CAACC,iBAAiB,CAAC;AACxD,CAACP,4BAA4B,EAAEM,MAAM,CAACE,iBAAiB,CAAC;AACxD;AACA,CAACP,wBAAwB,EAAE,CAAC,CAAC,CAAC,CAC/B,CAAC;;;AAEF,SAASS,eAAe,CAACC,CAAS,EAAEC,CAAU,EAAW;EACvD;EACA,IAAI,OAAOA,CAAC,KAAK,QAAQ,EAAE;IACzBjB,MAAM;IACJ,CAACc,oBAAoB,CAACI,GAAG,CAACD,CAAC,CAAC;IAC3B,GAAEA,CAAE,0DAAyD,CAC/D;;;IAEDjB,MAAM;IACJiB,CAAC,KAAKX,wBAAwB;IAC7B,GAAEW,CAAE,0DAAyD,CAC/D;;EACH;;EAEA,IAAIE,MAAM,CAACC,EAAE,CAACH,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;IACpB,OAAOX,wBAAwB;EACjC;;EAEA,OAAOC,kBAAkB,CAACW,GAAG,CAACD,CAAC,CAAC,GAAGV,kBAAkB,CAACc,GAAG,CAACJ,CAAC,CAAC,GAAGA,CAAC;AAClE;;AAEA,OAAO,SAASK,mBAAmB,CAACC,KAAwB,EAAU;EACpE,OAAOC,IAAI,CAACC,SAAS,CAACF,KAAK,EAAER,eAAe,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,OAAO,SAASW,2BAA2B,CAACH,KAAwB,EAAU;EAC5E,OAAOC,IAAI,CAACC,SAAS,CAACF,KAAK,EAAE,CAACP,CAAC,EAAEC,CAAC,KAAK;IACrC,IAAI,OAAOA,CAAC,KAAK,QAAQ,IAAIA,CAAC,KAAK,IAAI,EAAE;MACvC,OAAOhB,eAAe,CAACgB,CAAC,CAAC;IAC3B;;IAEA,OAAOF,eAAe,CAACC,CAAC,EAAEC,CAAC,CAAC;EAC9B,CAAC,CAAC;AACJ;;AAEA;;AAEA,SAASU,sBAAsB,CAACX,CAAS,EAAEC,CAAM,EAAO;EACtD,IAAIH,oBAAoB,CAACI,GAAG,CAACD,CAAC,CAAC,EAAE;IAC/B,OAAOH,oBAAoB,CAACO,GAAG,CAACJ,CAAC,CAAC;EACpC;;EAEA,OAAOA,CAAC;AACV;;AAEA,OAAO,SAASW,eAAe,CAACC,CAAS,EAAqB;EAC5D,OAAOL,IAAI,CAACM,KAAK,CAACD,CAAC,EAAEF,sBAAsB,CAAC;AAC9C"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js
new file mode 100644
index 0000000000..4cfa6faf58
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js
@@ -0,0 +1,156 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from '../../util/util.js';import {
+
+badParamValueChars,
+paramKeyIsPublic } from
+'../params_utils.js';
+
+import { parseParamValue } from './json_param_value.js';
+import {
+
+TestQueryMultiFile,
+TestQueryMultiTest,
+TestQueryMultiCase,
+TestQuerySingleCase } from
+'./query.js';
+import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';
+import { validQueryPart } from './validQueryPart.js';
+
+export function parseQuery(s) {
+ try {
+ return parseQueryImpl(s);
+ } catch (ex) {
+ if (ex instanceof Error) {
+ ex.message += '\n on: ' + s;
+ }
+ throw ex;
+ }
+}
+
+function parseQueryImpl(s) {
+ // Undo encodeURIComponentSelectively
+ s = decodeURIComponent(s);
+
+ // bigParts are: suite, file, test, params (note kBigSeparator could appear in params)
+ let suite;
+ let fileString;
+ let testString;
+ let paramsString;
+ {
+ const i1 = s.indexOf(kBigSeparator);
+ assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`);
+ suite = s.substring(0, i1);
+ const i2 = s.indexOf(kBigSeparator, i1 + 1);
+ if (i2 === -1) {
+ fileString = s.substring(i1 + 1);
+ } else {
+ fileString = s.substring(i1 + 1, i2);
+ const i3 = s.indexOf(kBigSeparator, i2 + 1);
+ if (i3 === -1) {
+ testString = s.substring(i2 + 1);
+ } else {
+ testString = s.substring(i2 + 1, i3);
+ paramsString = s.substring(i3 + 1);
+ }
+ }
+ }
+
+ const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);
+
+ if (testString === undefined) {
+ // Query is file-level
+ assert(
+ filePathHasWildcard,
+ `File-level query without wildcard ${kWildcard}. Did you want a file-level query \
+(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`);
+
+ return new TestQueryMultiFile(suite, file);
+ }
+ assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
+
+ const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator);
+
+ if (paramsString === undefined) {
+ // Query is test-level
+ assert(
+ testPathHasWildcard,
+ `Test-level query without wildcard ${kWildcard}; did you want a test-level query \
+(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`);
+
+ assert(file.length > 0, 'File part of test-level query was empty (::)');
+ return new TestQueryMultiTest(suite, file, test);
+ }
+
+ // Query is case-level
+ assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
+
+ const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart(
+ paramsString,
+ kParamSeparator);
+
+
+ assert(test.length > 0, 'Test part of case-level query was empty (::)');
+
+ const params = {};
+ for (const paramPart of paramsParts) {
+ const [k, v] = parseSingleParam(paramPart);
+ assert(validQueryPart.test(k), `param key names must match ${validQueryPart}`);
+ params[k] = v;
+ }
+ if (paramsHasWildcard) {
+ return new TestQueryMultiCase(suite, file, test, params);
+ } else {
+ return new TestQuerySingleCase(suite, file, test, params);
+ }
+}
+
+// webgpu:a,b,* or webgpu:a,b,c:*
+const kExampleQueries = `\
+webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \
+webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`;
+
+function parseBigPart(
+s,
+separator)
+{
+ if (s === '') {
+ return { parts: [], wildcard: false };
+ }
+ const parts = s.split(separator);
+
+ let endsWithWildcard = false;
+ for (const [i, part] of parts.entries()) {
+ if (i === parts.length - 1) {
+ endsWithWildcard = part === kWildcard;
+ }
+ assert(
+ part.indexOf(kWildcard) === -1 || endsWithWildcard,
+ `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`);
+
+ }
+ if (endsWithWildcard) {
+ // Remove the last element of the array (which is just the wildcard).
+ parts.length = parts.length - 1;
+ }
+ return { parts, wildcard: endsWithWildcard };
+}
+
+function parseSingleParam(paramSubstring) {
+ assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)');
+ const i = paramSubstring.indexOf('=');
+ assert(i !== -1, 'Param in a query must be of form key=value');
+ const k = paramSubstring.substring(0, i);
+ assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)');
+ const v = paramSubstring.substring(i + 1);
+ return [k, parseSingleParamValue(v)];
+}
+
+function parseSingleParamValue(s) {
+ assert(
+ !badParamValueChars.test(s),
+ `param value must not match ${badParamValueChars} - was ${s}`);
+
+ return parseParamValue(s);
+}
+//# sourceMappingURL=parseQuery.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map
new file mode 100644
index 0000000000..4580b15bf4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"parseQuery.js","names":["assert","badParamValueChars","paramKeyIsPublic","parseParamValue","TestQueryMultiFile","TestQueryMultiTest","TestQueryMultiCase","TestQuerySingleCase","kBigSeparator","kWildcard","kPathSeparator","kParamSeparator","validQueryPart","parseQuery","s","parseQueryImpl","ex","Error","message","decodeURIComponent","suite","fileString","testString","paramsString","i1","indexOf","substring","i2","i3","parts","file","wildcard","filePathHasWildcard","parseBigPart","undefined","test","testPathHasWildcard","length","paramsParts","paramsHasWildcard","params","paramPart","k","v","parseSingleParam","kExampleQueries","separator","split","endsWithWildcard","i","part","entries","paramSubstring","parseSingleParamValue"],"sources":["../../../../src/common/internal/query/parseQuery.ts"],"sourcesContent":["import { assert } from '../../util/util.js';\nimport {\n TestParamsRW,\n JSONWithUndefined,\n badParamValueChars,\n paramKeyIsPublic,\n} from '../params_utils.js';\n\nimport { parseParamValue } from './json_param_value.js';\nimport {\n TestQuery,\n TestQueryMultiFile,\n TestQueryMultiTest,\n TestQueryMultiCase,\n TestQuerySingleCase,\n} from './query.js';\nimport { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';\nimport { validQueryPart } from './validQueryPart.js';\n\nexport function parseQuery(s: string): TestQuery {\n try {\n return parseQueryImpl(s);\n } catch (ex) {\n if (ex instanceof Error) {\n ex.message += '\\n on: ' + s;\n }\n throw ex;\n }\n}\n\nfunction parseQueryImpl(s: string): TestQuery {\n // Undo encodeURIComponentSelectively\n s = decodeURIComponent(s);\n\n // bigParts are: suite, file, test, params (note kBigSeparator could appear in params)\n let suite: string;\n let fileString: string | undefined;\n let testString: string | undefined;\n let paramsString: string | undefined;\n {\n const i1 = s.indexOf(kBigSeparator);\n assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`);\n suite = s.substring(0, i1);\n const i2 = s.indexOf(kBigSeparator, i1 + 1);\n if (i2 === -1) {\n fileString = s.substring(i1 + 1);\n } else {\n fileString = s.substring(i1 + 1, i2);\n const i3 = s.indexOf(kBigSeparator, i2 + 1);\n if (i3 === -1) {\n testString = s.substring(i2 + 1);\n } else {\n testString = s.substring(i2 + 1, i3);\n paramsString = s.substring(i3 + 1);\n }\n }\n }\n\n const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);\n\n if (testString === undefined) {\n // Query is file-level\n assert(\n filePathHasWildcard,\n `File-level query without wildcard ${kWildcard}. Did you want a file-level query \\\n(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`\n );\n return new TestQueryMultiFile(suite, file);\n }\n assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);\n\n const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator);\n\n if (paramsString === undefined) {\n // Query is test-level\n assert(\n testPathHasWildcard,\n `Test-level query without wildcard ${kWildcard}; did you want a test-level query \\\n(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`\n );\n assert(file.length > 0, 'File part of test-level query was empty (::)');\n return new TestQueryMultiTest(suite, file, test);\n }\n\n // Query is case-level\n assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);\n\n const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart(\n paramsString,\n kParamSeparator\n );\n\n assert(test.length > 0, 'Test part of case-level query was empty (::)');\n\n const params: TestParamsRW = {};\n for (const paramPart of paramsParts) {\n const [k, v] = parseSingleParam(paramPart);\n assert(validQueryPart.test(k), `param key names must match ${validQueryPart}`);\n params[k] = v;\n }\n if (paramsHasWildcard) {\n return new TestQueryMultiCase(suite, file, test, params);\n } else {\n return new TestQuerySingleCase(suite, file, test, params);\n }\n}\n\n// webgpu:a,b,* or webgpu:a,b,c:*\nconst kExampleQueries = `\\\nwebgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \\\nwebgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`;\n\nfunction parseBigPart(\n s: string,\n separator: typeof kParamSeparator | typeof kPathSeparator\n): { parts: string[]; wildcard: boolean } {\n if (s === '') {\n return { parts: [], wildcard: false };\n }\n const parts = s.split(separator);\n\n let endsWithWildcard = false;\n for (const [i, part] of parts.entries()) {\n if (i === parts.length - 1) {\n endsWithWildcard = part === kWildcard;\n }\n assert(\n part.indexOf(kWildcard) === -1 || endsWithWildcard,\n `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`\n );\n }\n if (endsWithWildcard) {\n // Remove the last element of the array (which is just the wildcard).\n parts.length = parts.length - 1;\n }\n return { parts, wildcard: endsWithWildcard };\n}\n\nfunction parseSingleParam(paramSubstring: string): [string, JSONWithUndefined] {\n assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)');\n const i = paramSubstring.indexOf('=');\n assert(i !== -1, 'Param in a query must be of form key=value');\n const k = paramSubstring.substring(0, i);\n assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)');\n const v = paramSubstring.substring(i + 1);\n return [k, parseSingleParamValue(v)];\n}\n\nfunction parseSingleParamValue(s: string): JSONWithUndefined {\n assert(\n !badParamValueChars.test(s),\n `param value must not match ${badParamValueChars} - was ${s}`\n );\n return parseParamValue(s);\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,MAAM,QAAQ,oBAAoB,CAC3C;;AAGEC,kBAAkB;AAClBC,gBAAgB;AACX,oBAAoB;;AAE3B,SAASC,eAAe,QAAQ,uBAAuB;AACvD;;AAEEC,kBAAkB;AAClBC,kBAAkB;AAClBC,kBAAkB;AAClBC,mBAAmB;AACd,YAAY;AACnB,SAASC,aAAa,EAAEC,SAAS,EAAEC,cAAc,EAAEC,eAAe,QAAQ,iBAAiB;AAC3F,SAASC,cAAc,QAAQ,qBAAqB;;AAEpD,OAAO,SAASC,UAAU,CAACC,CAAS,EAAa;EAC/C,IAAI;IACF,OAAOC,cAAc,CAACD,CAAC,CAAC;EAC1B,CAAC,CAAC,OAAOE,EAAE,EAAE;IACX,IAAIA,EAAE,YAAYC,KAAK,EAAE;MACvBD,EAAE,CAACE,OAAO,IAAI,UAAU,GAAGJ,CAAC;IAC9B;IACA,MAAME,EAAE;EACV;AACF;;AAEA,SAASD,cAAc,CAACD,CAAS,EAAa;EAC5C;EACAA,CAAC,GAAGK,kBAAkB,CAACL,CAAC,CAAC;;EAEzB;EACA,IAAIM,KAAa;EACjB,IAAIC,UAA8B;EAClC,IAAIC,UAA8B;EAClC,IAAIC,YAAgC;EACpC;IACE,MAAMC,EAAE,GAAGV,CAAC,CAACW,OAAO,CAACjB,aAAa,CAAC;IACnCR,MAAM,CAACwB,EAAE,KAAK,CAAC,CAAC,EAAG,uCAAsChB,aAAc,EAAC,CAAC;IACzEY,KAAK,GAAGN,CAAC,CAACY,SAAS,CAAC,CAAC,EAAEF,EAAE,CAAC;IAC1B,MAAMG,EAAE,GAAGb,CAAC,CAACW,OAAO,CAACjB,aAAa,EAAEgB,EAAE,GAAG,CAAC,CAAC;IAC3C,IAAIG,EAAE,KAAK,CAAC,CAAC,EAAE;MACbN,UAAU,GAAGP,CAAC,CAACY,SAAS,CAACF,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC,MAAM;MACLH,UAAU,GAAGP,CAAC,CAACY,SAAS,CAACF,EAAE,GAAG,CAAC,EAAEG,EAAE,CAAC;MACpC,MAAMC,EAAE,GAAGd,CAAC,CAACW,OAAO,CAACjB,aAAa,EAAEmB,EAAE,GAAG,CAAC,CAAC;MAC3C,IAAIC,EAAE,KAAK,CAAC,CAAC,EAAE;QACbN,UAAU,GAAGR,CAAC,CAACY,SAAS,CAACC,EAAE,GAAG,CAAC,CAAC;MAClC,CAAC,MAAM;QACLL,UAAU,GAAGR,CAAC,CAACY,SAAS,CAACC,EAAE,GAAG,CAAC,EAAEC,EAAE,CAAC;QACpCL,YAAY,GAAGT,CAAC,CAACY,SAAS,CAACE,EAAE,GAAG,CAAC,CAAC;MACpC;IACF;EACF;;EAEA,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,mBAAmB,CAAC,CAAC,GAAGC,YAAY,CAACZ,UAAU,EAAEX,cAAc,CAAC;;EAE/F,IAAIY,UAAU,KAAKY,SAAS,EAAE;IAC5B;IACAlC,MAAM;IACJgC,mBAAmB;IAClB,qCAAoCvB,SAAU;AACrD,UAAUC,cAAe,GAAED,SAAU,iCAAgCD,aAAc,GAAEC,SAAU,IAAG,CAC7F;;IACD,OAAO,IAAIL,kBAAkB,CAACgB,KAAK,EAAEU,IAAI,CAAC;EAC5C;EACA9B,MAAM,CAAC,CAACgC,mBAAmB,EAAG,YAAWvB,SAAU,yCAAwC,CAAC;;EAE5F,MAAM,EAAEoB,KAAK,EAAEM,IAAI,EAAEJ,QAAQ,EAAEK,mBAAmB,CAAC,CAAC,GAAGH,YAAY,CAACX,UAAU,EAAEZ,cAAc,CAAC;;EAE/F,IAAIa,YAAY,KAAKW,SAAS,EAAE;IAC9B;IACAlC,MAAM;IACJoC,mBAAmB;IAClB,qCAAoC3B,SAAU;AACrD,UAAUC,cAAe,GAAED,SAAU,iCAAgCD,aAAc,GAAEC,SAAU,IAAG,CAC7F;;IACDT,MAAM,CAAC8B,IAAI,CAACO,MAAM,GAAG,CAAC,EAAE,8CAA8C,CAAC;IACvE,OAAO,IAAIhC,kBAAkB,CAACe,KAAK,EAAEU,IAAI,EAAEK,IAAI,CAAC;EAClD;;EAEA;EACAnC,MAAM,CAAC,CAACoC,mBAAmB,EAAG,YAAW3B,SAAU,yCAAwC,CAAC;;EAE5F,MAAM,EAAEoB,KAAK,EAAES,WAAW,EAAEP,QAAQ,EAAEQ,iBAAiB,CAAC,CAAC,GAAGN,YAAY;EACtEV,YAAY;EACZZ,eAAe,CAChB;;;EAEDX,MAAM,CAACmC,IAAI,CAACE,MAAM,GAAG,CAAC,EAAE,8CAA8C,CAAC;;EAEvE,MAAMG,MAAoB,GAAG,CAAC,CAAC;EAC/B,KAAK,MAAMC,SAAS,IAAIH,WAAW,EAAE;IACnC,MAAM,CAACI,CAAC,EAAEC,CAAC,CAAC,GAAGC,gBAAgB,CAACH,SAAS,CAAC;IAC1CzC,MAAM,CAACY,cAAc,CAACuB,IAAI,CAACO,CAAC,CAAC,EAAG,8BAA6B9B,cAAe,EAAC,CAAC;IAC9E4B,MAAM,CAACE,CAAC,CAAC,GAAGC,CAAC;EACf;EACA,IAAIJ,iBAAiB,EAAE;IACrB,OAAO,IAAIjC,kBAAkB,CAACc,KAAK,EAAEU,IAAI,EAAEK,IAAI,EAAEK,MAAM,CAAC;EAC1D,CAAC,MAAM;IACL,OAAO,IAAIjC,mBAAmB,CAACa,KAAK,EAAEU,IAAI,EAAEK,IAAI,EAAEK,MAAM,CAAC;EAC3D;AACF;;AAEA;AACA,MAAMK,eAAe,GAAI;AACzB,QAAQrC,aAAc,IAAGE,cAAe,IAAGA,cAAe,GAAED,SAAU;AACtE,QAAQD,aAAc,IAAGE,cAAe,IAAGA,cAAe,IAAGF,aAAc,GAAEC,SAAU,EAAC;;AAExF,SAASwB,YAAY;AACnBnB,CAAS;AACTgC,SAAyD;AACjB;EACxC,IAAIhC,CAAC,KAAK,EAAE,EAAE;IACZ,OAAO,EAAEe,KAAK,EAAE,EAAE,EAAEE,QAAQ,EAAE,KAAK,CAAC,CAAC;EACvC;EACA,MAAMF,KAAK,GAAGf,CAAC,CAACiC,KAAK,CAACD,SAAS,CAAC;;EAEhC,IAAIE,gBAAgB,GAAG,KAAK;EAC5B,KAAK,MAAM,CAACC,CAAC,EAAEC,IAAI,CAAC,IAAIrB,KAAK,CAACsB,OAAO,EAAE,EAAE;IACvC,IAAIF,CAAC,KAAKpB,KAAK,CAACQ,MAAM,GAAG,CAAC,EAAE;MAC1BW,gBAAgB,GAAGE,IAAI,KAAKzC,SAAS;IACvC;IACAT,MAAM;IACJkD,IAAI,CAACzB,OAAO,CAAChB,SAAS,CAAC,KAAK,CAAC,CAAC,IAAIuC,gBAAgB;IACjD,YAAWvC,SAAU,+CAA8CoC,eAAgB,GAAE,CACvF;;EACH;EACA,IAAIG,gBAAgB,EAAE;IACpB;IACAnB,KAAK,CAACQ,MAAM,GAAGR,KAAK,CAACQ,MAAM,GAAG,CAAC;EACjC;EACA,OAAO,EAAER,KAAK,EAAEE,QAAQ,EAAEiB,gBAAgB,CAAC,CAAC;AAC9C;;AAEA,SAASJ,gBAAgB,CAACQ,cAAsB,EAA+B;EAC7EpD,MAAM,CAACoD,cAAc,KAAK,EAAE,EAAE,iEAAiE,CAAC;EAChG,MAAMH,CAAC,GAAGG,cAAc,CAAC3B,OAAO,CAAC,GAAG,CAAC;EACrCzB,MAAM,CAACiD,CAAC,KAAK,CAAC,CAAC,EAAE,4CAA4C,CAAC;EAC9D,MAAMP,CAAC,GAAGU,cAAc,CAAC1B,SAAS,CAAC,CAAC,EAAEuB,CAAC,CAAC;EACxCjD,MAAM,CAACE,gBAAgB,CAACwC,CAAC,CAAC,EAAE,qDAAqD,CAAC;EAClF,MAAMC,CAAC,GAAGS,cAAc,CAAC1B,SAAS,CAACuB,CAAC,GAAG,CAAC,CAAC;EACzC,OAAO,CAACP,CAAC,EAAEW,qBAAqB,CAACV,CAAC,CAAC,CAAC;AACtC;;AAEA,SAASU,qBAAqB,CAACvC,CAAS,EAAqB;EAC3Dd,MAAM;EACJ,CAACC,kBAAkB,CAACkC,IAAI,CAACrB,CAAC,CAAC;EAC1B,8BAA6Bb,kBAAmB,UAASa,CAAE,EAAC,CAC9D;;EACD,OAAOX,eAAe,CAACW,CAAC,CAAC;AAC3B"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js
new file mode 100644
index 0000000000..cb09f6ea8a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js
@@ -0,0 +1,263 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { optionEnabled } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js';
+
+
+import { compareQueries, Ordering } from './compare.js';
+import { encodeURIComponentSelectively } from './encode_selectively.js';
+import { parseQuery } from './parseQuery.js';
+import { kBigSeparator, kPathSeparator, kWildcard } from './separators.js';
+import { stringifyPublicParams } from './stringify_params.js';
+
+/**
+ * Represents a test query of some level.
+ *
+ * TestQuery types are immutable.
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * A multi-file test query, like `s:*` or `s:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQueryMultiFile {
+ level = 1;
+ isMultiFile = true;
+
+
+
+ constructor(suite, file) {
+ this.suite = suite;
+ this.filePathParts = [...file];
+ }
+
+ get depthInLevel() {
+ return this.filePathParts.length;
+ }
+
+ toString() {
+ return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator));
+ }
+
+ toStringHelper() {
+ return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)];
+ }
+}
+
+/**
+ * A multi-test test query, like `s:f:*` or `s:f:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQueryMultiTest extends TestQueryMultiFile {
+ level = 2;
+ isMultiFile = false;
+ isMultiTest = true;
+
+
+ constructor(suite, file, test) {
+ super(suite, file);
+ assert(file.length > 0, 'multi-test (or finer) query must have file-path');
+ this.testPathParts = [...test];
+ }
+
+ get depthInLevel() {
+ return this.testPathParts.length;
+ }
+
+ toStringHelper() {
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ [...this.testPathParts, kWildcard].join(kPathSeparator)];
+
+ }
+}
+
+/**
+ * A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args), except for param values
+ * (which aren't normally supposed to change; they're marked readonly in TestParams).
+ */
+export class TestQueryMultiCase extends TestQueryMultiTest {
+ level = 3;
+ isMultiTest = false;
+ isMultiCase = true;
+
+
+ constructor(suite, file, test, params) {
+ super(suite, file, test);
+ assert(test.length > 0, 'multi-case (or finer) query must have test-path');
+ this.params = { ...params };
+ }
+
+ get depthInLevel() {
+ return Object.keys(this.params).length;
+ }
+
+ toStringHelper() {
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ this.testPathParts.join(kPathSeparator),
+ stringifyPublicParams(this.params, true)];
+
+ }
+}
+
+/**
+ * A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQuerySingleCase extends TestQueryMultiCase {
+ level = 4;
+ isMultiCase = false;
+
+ get depthInLevel() {
+ return 0;
+ }
+
+ toStringHelper() {
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ this.testPathParts.join(kPathSeparator),
+ stringifyPublicParams(this.params)];
+
+ }
+}
+
+/**
+ * Parse raw expectations input into TestQueryWithExpectation[], filtering so that only
+ * expectations that are relevant for the provided query and wptURL.
+ *
+ * `rawExpectations` should be @type {{ query: string, expectation: Expectation }[]}
+ *
+ * The `rawExpectations` are parsed and validated that they are in the correct format.
+ * If `wptURL` is passed, the query string should be of the full path format such
+ * as `path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;*`.
+ * If `wptURL` is `undefined`, the query string should be only the query
+ * `suite:test_path:test_name:foo=1;bar=2;*`.
+ */
+export function parseExpectationsForTestQuery(
+rawExpectations,
+
+
+
+
+
+query,
+wptURL)
+{
+ if (!Array.isArray(rawExpectations)) {
+ unreachable('Expectations should be an array');
+ }
+ const expectations = [];
+ for (const entry of rawExpectations) {
+ assert(typeof entry === 'object');
+ const rawExpectation = entry;
+ assert(rawExpectation.query !== undefined, 'Expectation missing query string');
+ assert(rawExpectation.expectation !== undefined, 'Expectation missing expectation string');
+
+ let expectationQuery;
+ if (wptURL !== undefined) {
+ const expectationURL = new URL(`${wptURL.origin}/${entry.query}`);
+ if (expectationURL.pathname !== wptURL.pathname) {
+ continue;
+ }
+ assert(
+ expectationURL.pathname === wptURL.pathname,
+ `Invalid expectation path ${expectationURL.pathname}
+Expectation should be of the form path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;...
+ `);
+
+
+ const params = expectationURL.searchParams;
+ if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) {
+ continue;
+ }
+
+ const qs = params.getAll('q');
+ assert(qs.length === 1, 'currently, there must be exactly one ?q= in the expectation string');
+ expectationQuery = parseQuery(qs[0]);
+ } else {
+ expectationQuery = parseQuery(entry.query);
+ }
+
+ // Strip params from multicase expectations so that an expectation of foo=2;*
+ // is stored if the test query is bar=3;*
+ const queryForFilter =
+ expectationQuery instanceof TestQueryMultiCase ?
+ new TestQueryMultiCase(
+ expectationQuery.suite,
+ expectationQuery.filePathParts,
+ expectationQuery.testPathParts,
+ {}) :
+
+ expectationQuery;
+
+ if (compareQueries(query, queryForFilter) === Ordering.Unordered) {
+ continue;
+ }
+
+ switch (entry.expectation) {
+ case 'pass':
+ case 'skip':
+ case 'fail':
+ break;
+ default:
+ unreachable(`Invalid expectation ${entry.expectation}`);}
+
+
+ expectations.push({
+ query: expectationQuery,
+ expectation: entry.expectation
+ });
+ }
+ return expectations;
+}
+
+/**
+ * For display purposes only, produces a "relative" query string from parent to child.
+ * Used in the wpt runtime to reduce the verbosity of logs.
+ */
+export function relativeQueryString(parent, child) {
+ const ordering = compareQueries(parent, child);
+ if (ordering === Ordering.Equal) {
+ return '';
+ } else if (ordering === Ordering.StrictSuperset) {
+ const parentString = parent.toString();
+ assert(parentString.endsWith(kWildcard));
+ const childString = child.toString();
+ assert(
+ childString.startsWith(parentString.substring(0, parentString.length - 2)),
+ 'impossible?: childString does not start with parentString[:-2]');
+
+ return childString.substring(parentString.length - 2);
+ } else {
+ unreachable(
+ `relativeQueryString arguments have invalid ordering ${ordering}:\n${parent}\n${child}`);
+
+ }
+}
+//# sourceMappingURL=query.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map
new file mode 100644
index 0000000000..09d712c589
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"query.js","names":["optionEnabled","assert","unreachable","compareQueries","Ordering","encodeURIComponentSelectively","parseQuery","kBigSeparator","kPathSeparator","kWildcard","stringifyPublicParams","TestQueryMultiFile","level","isMultiFile","constructor","suite","file","filePathParts","depthInLevel","length","toString","toStringHelper","join","TestQueryMultiTest","isMultiTest","test","testPathParts","TestQueryMultiCase","isMultiCase","params","Object","keys","TestQuerySingleCase","parseExpectationsForTestQuery","rawExpectations","query","wptURL","Array","isArray","expectations","entry","rawExpectation","undefined","expectation","expectationQuery","expectationURL","URL","origin","pathname","searchParams","qs","getAll","queryForFilter","Unordered","push","relativeQueryString","parent","child","ordering","Equal","StrictSuperset","parentString","endsWith","childString","startsWith","substring"],"sources":["../../../../src/common/internal/query/query.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { optionEnabled } from '../../runtime/helper/options.js';\nimport { assert, unreachable } from '../../util/util.js';\nimport { Expectation } from '../logging/result.js';\n\nimport { compareQueries, Ordering } from './compare.js';\nimport { encodeURIComponentSelectively } from './encode_selectively.js';\nimport { parseQuery } from './parseQuery.js';\nimport { kBigSeparator, kPathSeparator, kWildcard } from './separators.js';\nimport { stringifyPublicParams } from './stringify_params.js';\n\n/**\n * Represents a test query of some level.\n *\n * TestQuery types are immutable.\n */\nexport type TestQuery =\n | TestQuerySingleCase\n | TestQueryMultiCase\n | TestQueryMultiTest\n | TestQueryMultiFile;\n\n/**\n * - 1 = MultiFile.\n * - 2 = MultiTest.\n * - 3 = MultiCase.\n * - 4 = SingleCase.\n */\nexport type TestQueryLevel = 1 | 2 | 3 | 4;\n\nexport interface TestQueryWithExpectation {\n query: TestQuery;\n expectation: Expectation;\n}\n\n/**\n * A multi-file test query, like `s:*` or `s:a,b,*`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQueryMultiFile {\n readonly level: TestQueryLevel = 1;\n readonly isMultiFile: boolean = true;\n readonly suite: string;\n readonly filePathParts: readonly string[];\n\n constructor(suite: string, file: readonly string[]) {\n this.suite = suite;\n this.filePathParts = [...file];\n }\n\n get depthInLevel() {\n return this.filePathParts.length;\n }\n\n toString(): string {\n return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator));\n }\n\n protected toStringHelper(): string[] {\n return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)];\n }\n}\n\n/**\n * A multi-test test query, like `s:f:*` or `s:f:a,b,*`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQueryMultiTest extends TestQueryMultiFile {\n readonly level: TestQueryLevel = 2;\n readonly isMultiFile: false = false;\n readonly isMultiTest: boolean = true;\n readonly testPathParts: readonly string[];\n\n constructor(suite: string, file: readonly string[], test: readonly string[]) {\n super(suite, file);\n assert(file.length > 0, 'multi-test (or finer) query must have file-path');\n this.testPathParts = [...test];\n }\n\n get depthInLevel() {\n return this.testPathParts.length;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n [...this.testPathParts, kWildcard].join(kPathSeparator),\n ];\n }\n}\n\n/**\n * A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`.\n *\n * Immutable (makes copies of constructor args), except for param values\n * (which aren't normally supposed to change; they're marked readonly in TestParams).\n */\nexport class TestQueryMultiCase extends TestQueryMultiTest {\n readonly level: TestQueryLevel = 3;\n readonly isMultiTest: false = false;\n readonly isMultiCase: boolean = true;\n readonly params: TestParams;\n\n constructor(suite: string, file: readonly string[], test: readonly string[], params: TestParams) {\n super(suite, file, test);\n assert(test.length > 0, 'multi-case (or finer) query must have test-path');\n this.params = { ...params };\n }\n\n get depthInLevel() {\n return Object.keys(this.params).length;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n this.testPathParts.join(kPathSeparator),\n stringifyPublicParams(this.params, true),\n ];\n }\n}\n\n/**\n * A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQuerySingleCase extends TestQueryMultiCase {\n readonly level: TestQueryLevel = 4;\n readonly isMultiCase: false = false;\n\n get depthInLevel() {\n return 0;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n this.testPathParts.join(kPathSeparator),\n stringifyPublicParams(this.params),\n ];\n }\n}\n\n/**\n * Parse raw expectations input into TestQueryWithExpectation[], filtering so that only\n * expectations that are relevant for the provided query and wptURL.\n *\n * `rawExpectations` should be @type {{ query: string, expectation: Expectation }[]}\n *\n * The `rawExpectations` are parsed and validated that they are in the correct format.\n * If `wptURL` is passed, the query string should be of the full path format such\n * as `path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;*`.\n * If `wptURL` is `undefined`, the query string should be only the query\n * `suite:test_path:test_name:foo=1;bar=2;*`.\n */\nexport function parseExpectationsForTestQuery(\n rawExpectations:\n | unknown\n | {\n query: string;\n expectation: Expectation;\n }[],\n query: TestQuery,\n wptURL?: URL\n) {\n if (!Array.isArray(rawExpectations)) {\n unreachable('Expectations should be an array');\n }\n const expectations: TestQueryWithExpectation[] = [];\n for (const entry of rawExpectations) {\n assert(typeof entry === 'object');\n const rawExpectation = entry as { query?: string; expectation?: string };\n assert(rawExpectation.query !== undefined, 'Expectation missing query string');\n assert(rawExpectation.expectation !== undefined, 'Expectation missing expectation string');\n\n let expectationQuery: TestQuery;\n if (wptURL !== undefined) {\n const expectationURL = new URL(`${wptURL.origin}/${entry.query}`);\n if (expectationURL.pathname !== wptURL.pathname) {\n continue;\n }\n assert(\n expectationURL.pathname === wptURL.pathname,\n `Invalid expectation path ${expectationURL.pathname}\nExpectation should be of the form path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;...\n `\n );\n\n const params = expectationURL.searchParams;\n if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) {\n continue;\n }\n\n const qs = params.getAll('q');\n assert(qs.length === 1, 'currently, there must be exactly one ?q= in the expectation string');\n expectationQuery = parseQuery(qs[0]);\n } else {\n expectationQuery = parseQuery(entry.query);\n }\n\n // Strip params from multicase expectations so that an expectation of foo=2;*\n // is stored if the test query is bar=3;*\n const queryForFilter =\n expectationQuery instanceof TestQueryMultiCase\n ? new TestQueryMultiCase(\n expectationQuery.suite,\n expectationQuery.filePathParts,\n expectationQuery.testPathParts,\n {}\n )\n : expectationQuery;\n\n if (compareQueries(query, queryForFilter) === Ordering.Unordered) {\n continue;\n }\n\n switch (entry.expectation) {\n case 'pass':\n case 'skip':\n case 'fail':\n break;\n default:\n unreachable(`Invalid expectation ${entry.expectation}`);\n }\n\n expectations.push({\n query: expectationQuery,\n expectation: entry.expectation,\n });\n }\n return expectations;\n}\n\n/**\n * For display purposes only, produces a \"relative\" query string from parent to child.\n * Used in the wpt runtime to reduce the verbosity of logs.\n */\nexport function relativeQueryString(parent: TestQuery, child: TestQuery): string {\n const ordering = compareQueries(parent, child);\n if (ordering === Ordering.Equal) {\n return '';\n } else if (ordering === Ordering.StrictSuperset) {\n const parentString = parent.toString();\n assert(parentString.endsWith(kWildcard));\n const childString = child.toString();\n assert(\n childString.startsWith(parentString.substring(0, parentString.length - 2)),\n 'impossible?: childString does not start with parentString[:-2]'\n );\n return childString.substring(parentString.length - 2);\n } else {\n unreachable(\n `relativeQueryString arguments have invalid ordering ${ordering}:\\n${parent}\\n${child}`\n );\n }\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,aAAa,QAAQ,iCAAiC,CAC/D,SAASC,MAAM,EAAEC,WAAW,QAAQ,oBAAoB;;;AAGxD,SAASC,cAAc,EAAEC,QAAQ,QAAQ,cAAc;AACvD,SAASC,6BAA6B,QAAQ,yBAAyB;AACvE,SAASC,UAAU,QAAQ,iBAAiB;AAC5C,SAASC,aAAa,EAAEC,cAAc,EAAEC,SAAS,QAAQ,iBAAiB;AAC1E,SAASC,qBAAqB,QAAQ,uBAAuB;;AAE7D;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;AAoBA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,kBAAkB,CAAC;EACrBC,KAAK,GAAmB,CAAC;EACzBC,WAAW,GAAY,IAAI;;;;EAIpCC,WAAW,CAACC,KAAa,EAAEC,IAAuB,EAAE;IAClD,IAAI,CAACD,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACE,aAAa,GAAG,CAAC,GAAGD,IAAI,CAAC;EAChC;;EAEA,IAAIE,YAAY,GAAG;IACjB,OAAO,IAAI,CAACD,aAAa,CAACE,MAAM;EAClC;;EAEAC,QAAQ,GAAW;IACjB,OAAOf,6BAA6B,CAAC,IAAI,CAACgB,cAAc,EAAE,CAACC,IAAI,CAACf,aAAa,CAAC,CAAC;EACjF;;EAEUc,cAAc,GAAa;IACnC,OAAO,CAAC,IAAI,CAACN,KAAK,EAAE,CAAC,GAAG,IAAI,CAACE,aAAa,EAAER,SAAS,CAAC,CAACa,IAAI,CAACd,cAAc,CAAC,CAAC;EAC9E;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMe,kBAAkB,SAASZ,kBAAkB,CAAC;EAChDC,KAAK,GAAmB,CAAC;EACzBC,WAAW,GAAU,KAAK;EAC1BW,WAAW,GAAY,IAAI;;;EAGpCV,WAAW,CAACC,KAAa,EAAEC,IAAuB,EAAES,IAAuB,EAAE;IAC3E,KAAK,CAACV,KAAK,EAAEC,IAAI,CAAC;IAClBf,MAAM,CAACe,IAAI,CAACG,MAAM,GAAG,CAAC,EAAE,iDAAiD,CAAC;IAC1E,IAAI,CAACO,aAAa,GAAG,CAAC,GAAGD,IAAI,CAAC;EAChC;;EAEA,IAAIP,YAAY,GAAG;IACjB,OAAO,IAAI,CAACQ,aAAa,CAACP,MAAM;EAClC;;EAEUE,cAAc,GAAa;IACnC,OAAO;IACL,IAAI,CAACN,KAAK;IACV,IAAI,CAACE,aAAa,CAACK,IAAI,CAACd,cAAc,CAAC;IACvC,CAAC,GAAG,IAAI,CAACkB,aAAa,EAAEjB,SAAS,CAAC,CAACa,IAAI,CAACd,cAAc,CAAC,CACxD;;EACH;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMmB,kBAAkB,SAASJ,kBAAkB,CAAC;EAChDX,KAAK,GAAmB,CAAC;EACzBY,WAAW,GAAU,KAAK;EAC1BI,WAAW,GAAY,IAAI;;;EAGpCd,WAAW,CAACC,KAAa,EAAEC,IAAuB,EAAES,IAAuB,EAAEI,MAAkB,EAAE;IAC/F,KAAK,CAACd,KAAK,EAAEC,IAAI,EAAES,IAAI,CAAC;IACxBxB,MAAM,CAACwB,IAAI,CAACN,MAAM,GAAG,CAAC,EAAE,iDAAiD,CAAC;IAC1E,IAAI,CAACU,MAAM,GAAG,EAAE,GAAGA,MAAM,CAAC,CAAC;EAC7B;;EAEA,IAAIX,YAAY,GAAG;IACjB,OAAOY,MAAM,CAACC,IAAI,CAAC,IAAI,CAACF,MAAM,CAAC,CAACV,MAAM;EACxC;;EAEUE,cAAc,GAAa;IACnC,OAAO;IACL,IAAI,CAACN,KAAK;IACV,IAAI,CAACE,aAAa,CAACK,IAAI,CAACd,cAAc,CAAC;IACvC,IAAI,CAACkB,aAAa,CAACJ,IAAI,CAACd,cAAc,CAAC;IACvCE,qBAAqB,CAAC,IAAI,CAACmB,MAAM,EAAE,IAAI,CAAC,CACzC;;EACH;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMG,mBAAmB,SAASL,kBAAkB,CAAC;EACjDf,KAAK,GAAmB,CAAC;EACzBgB,WAAW,GAAU,KAAK;;EAEnC,IAAIV,YAAY,GAAG;IACjB,OAAO,CAAC;EACV;;EAEUG,cAAc,GAAa;IACnC,OAAO;IACL,IAAI,CAACN,KAAK;IACV,IAAI,CAACE,aAAa,CAACK,IAAI,CAACd,cAAc,CAAC;IACvC,IAAI,CAACkB,aAAa,CAACJ,IAAI,CAACd,cAAc,CAAC;IACvCE,qBAAqB,CAAC,IAAI,CAACmB,MAAM,CAAC,CACnC;;EACH;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,6BAA6B;AAC3CC,eAKO;;;;;;AACPC,KAAgB;AAChBC,MAAY;AACZ;EACA,IAAI,CAACC,KAAK,CAACC,OAAO,CAACJ,eAAe,CAAC,EAAE;IACnChC,WAAW,CAAC,iCAAiC,CAAC;EAChD;EACA,MAAMqC,YAAwC,GAAG,EAAE;EACnD,KAAK,MAAMC,KAAK,IAAIN,eAAe,EAAE;IACnCjC,MAAM,CAAC,OAAOuC,KAAK,KAAK,QAAQ,CAAC;IACjC,MAAMC,cAAc,GAAGD,KAAiD;IACxEvC,MAAM,CAACwC,cAAc,CAACN,KAAK,KAAKO,SAAS,EAAE,kCAAkC,CAAC;IAC9EzC,MAAM,CAACwC,cAAc,CAACE,WAAW,KAAKD,SAAS,EAAE,wCAAwC,CAAC;;IAE1F,IAAIE,gBAA2B;IAC/B,IAAIR,MAAM,KAAKM,SAAS,EAAE;MACxB,MAAMG,cAAc,GAAG,IAAIC,GAAG,CAAE,GAAEV,MAAM,CAACW,MAAO,IAAGP,KAAK,CAACL,KAAM,EAAC,CAAC;MACjE,IAAIU,cAAc,CAACG,QAAQ,KAAKZ,MAAM,CAACY,QAAQ,EAAE;QAC/C;MACF;MACA/C,MAAM;MACJ4C,cAAc,CAACG,QAAQ,KAAKZ,MAAM,CAACY,QAAQ;MAC1C,4BAA2BH,cAAc,CAACG,QAAS;AAC5D;AACA,SAAS,CACF;;;MAED,MAAMnB,MAAM,GAAGgB,cAAc,CAACI,YAAY;MAC1C,IAAIjD,aAAa,CAAC,QAAQ,EAAE6B,MAAM,CAAC,KAAK7B,aAAa,CAAC,QAAQ,EAAEoC,MAAM,CAACa,YAAY,CAAC,EAAE;QACpF;MACF;;MAEA,MAAMC,EAAE,GAAGrB,MAAM,CAACsB,MAAM,CAAC,GAAG,CAAC;MAC7BlD,MAAM,CAACiD,EAAE,CAAC/B,MAAM,KAAK,CAAC,EAAE,oEAAoE,CAAC;MAC7FyB,gBAAgB,GAAGtC,UAAU,CAAC4C,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,MAAM;MACLN,gBAAgB,GAAGtC,UAAU,CAACkC,KAAK,CAACL,KAAK,CAAC;IAC5C;;IAEA;IACA;IACA,MAAMiB,cAAc;IAClBR,gBAAgB,YAAYjB,kBAAkB;IAC1C,IAAIA,kBAAkB;IACpBiB,gBAAgB,CAAC7B,KAAK;IACtB6B,gBAAgB,CAAC3B,aAAa;IAC9B2B,gBAAgB,CAAClB,aAAa;IAC9B,CAAC,CAAC,CACH;;IACDkB,gBAAgB;;IAEtB,IAAIzC,cAAc,CAACgC,KAAK,EAAEiB,cAAc,CAAC,KAAKhD,QAAQ,CAACiD,SAAS,EAAE;MAChE;IACF;;IAEA,QAAQb,KAAK,CAACG,WAAW;MACvB,KAAK,MAAM;MACX,KAAK,MAAM;MACX,KAAK,MAAM;QACT;MACF;QACEzC,WAAW,CAAE,uBAAsBsC,KAAK,CAACG,WAAY,EAAC,CAAC,CAAC;;;IAG5DJ,YAAY,CAACe,IAAI,CAAC;MAChBnB,KAAK,EAAES,gBAAgB;MACvBD,WAAW,EAAEH,KAAK,CAACG;IACrB,CAAC,CAAC;EACJ;EACA,OAAOJ,YAAY;AACrB;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASgB,mBAAmB,CAACC,MAAiB,EAAEC,KAAgB,EAAU;EAC/E,MAAMC,QAAQ,GAAGvD,cAAc,CAACqD,MAAM,EAAEC,KAAK,CAAC;EAC9C,IAAIC,QAAQ,KAAKtD,QAAQ,CAACuD,KAAK,EAAE;IAC/B,OAAO,EAAE;EACX,CAAC,MAAM,IAAID,QAAQ,KAAKtD,QAAQ,CAACwD,cAAc,EAAE;IAC/C,MAAMC,YAAY,GAAGL,MAAM,CAACpC,QAAQ,EAAE;IACtCnB,MAAM,CAAC4D,YAAY,CAACC,QAAQ,CAACrD,SAAS,CAAC,CAAC;IACxC,MAAMsD,WAAW,GAAGN,KAAK,CAACrC,QAAQ,EAAE;IACpCnB,MAAM;IACJ8D,WAAW,CAACC,UAAU,CAACH,YAAY,CAACI,SAAS,CAAC,CAAC,EAAEJ,YAAY,CAAC1C,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1E,gEAAgE,CACjE;;IACD,OAAO4C,WAAW,CAACE,SAAS,CAACJ,YAAY,CAAC1C,MAAM,GAAG,CAAC,CAAC;EACvD,CAAC,MAAM;IACLjB,WAAW;IACR,uDAAsDwD,QAAS,MAAKF,MAAO,KAAIC,KAAM,EAAC,CACxF;;EACH;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js
new file mode 100644
index 0000000000..cf0c130583
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js
@@ -0,0 +1,15 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /** Separator between big parts: suite:file:test:case */export const kBigSeparator = ':';
+/** Separator between path,to,file or path,to,test */
+export const kPathSeparator = ',';
+
+/** Separator between k=v;k=v */
+export const kParamSeparator = ';';
+
+/** Separator between key and value in k=v */
+export const kParamKVSeparator = '=';
+
+/** Final wildcard, if query is not single-case */
+export const kWildcard = '*';
+//# sourceMappingURL=separators.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map
new file mode 100644
index 0000000000..df7bd0c9ea
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"separators.js","names":["kBigSeparator","kPathSeparator","kParamSeparator","kParamKVSeparator","kWildcard"],"sources":["../../../../src/common/internal/query/separators.ts"],"sourcesContent":["/** Separator between big parts: suite:file:test:case */\nexport const kBigSeparator = ':';\n\n/** Separator between path,to,file or path,to,test */\nexport const kPathSeparator = ',';\n\n/** Separator between k=v;k=v */\nexport const kParamSeparator = ';';\n\n/** Separator between key and value in k=v */\nexport const kParamKVSeparator = '=';\n\n/** Final wildcard, if query is not single-case */\nexport const kWildcard = '*';\n"],"mappings":";AAAA;AAAA,G,CAAA,wDACA,OAAO,MAAMA,aAAa,GAAG,GAAG;AAEhC;AACA,OAAO,MAAMC,cAAc,GAAG,GAAG;;AAEjC;AACA,OAAO,MAAMC,eAAe,GAAG,GAAG;;AAElC;AACA,OAAO,MAAMC,iBAAiB,GAAG,GAAG;;AAEpC;AACA,OAAO,MAAMC,SAAS,GAAG,GAAG"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js
new file mode 100644
index 0000000000..014f502cd4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js
@@ -0,0 +1,45 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from '../../util/util.js';import { badParamValueChars, paramKeyIsPublic } from '../params_utils.js';
+
+import { stringifyParamValue, stringifyParamValueUniquely } from './json_param_value.js';
+import { kParamKVSeparator, kParamSeparator, kWildcard } from './separators.js';
+
+export function stringifyPublicParams(p, addWildcard = false) {
+ const parts = Object.keys(p).
+ filter((k) => paramKeyIsPublic(k)).
+ map((k) => stringifySingleParam(k, p[k]));
+
+ if (addWildcard) parts.push(kWildcard);
+
+ return parts.join(kParamSeparator);
+}
+
+/**
+ * An _approximately_ unique string representing a CaseParams value.
+ */
+export function stringifyPublicParamsUniquely(p) {
+ const keys = Object.keys(p).sort();
+ return keys.
+ filter((k) => paramKeyIsPublic(k)).
+ map((k) => stringifySingleParamUniquely(k, p[k])).
+ join(kParamSeparator);
+}
+
+export function stringifySingleParam(k, v) {
+ return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`;
+}
+
+function stringifySingleParamUniquely(k, v) {
+ return `${k}${kParamKVSeparator}${stringifyParamValueUniquely(v)}`;
+}
+
+function stringifySingleParamValue(v) {
+ const s = stringifyParamValue(v);
+ assert(
+ !badParamValueChars.test(s),
+ `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`);
+
+ return s;
+}
+//# sourceMappingURL=stringify_params.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map
new file mode 100644
index 0000000000..60e963e6cb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"stringify_params.js","names":["assert","badParamValueChars","paramKeyIsPublic","stringifyParamValue","stringifyParamValueUniquely","kParamKVSeparator","kParamSeparator","kWildcard","stringifyPublicParams","p","addWildcard","parts","Object","keys","filter","k","map","stringifySingleParam","push","join","stringifyPublicParamsUniquely","sort","stringifySingleParamUniquely","v","stringifySingleParamValue","s","test"],"sources":["../../../../src/common/internal/query/stringify_params.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { assert } from '../../util/util.js';\nimport { JSONWithUndefined, badParamValueChars, paramKeyIsPublic } from '../params_utils.js';\n\nimport { stringifyParamValue, stringifyParamValueUniquely } from './json_param_value.js';\nimport { kParamKVSeparator, kParamSeparator, kWildcard } from './separators.js';\n\nexport function stringifyPublicParams(p: TestParams, addWildcard = false): string {\n const parts = Object.keys(p)\n .filter(k => paramKeyIsPublic(k))\n .map(k => stringifySingleParam(k, p[k]));\n\n if (addWildcard) parts.push(kWildcard);\n\n return parts.join(kParamSeparator);\n}\n\n/**\n * An _approximately_ unique string representing a CaseParams value.\n */\nexport function stringifyPublicParamsUniquely(p: TestParams): string {\n const keys = Object.keys(p).sort();\n return keys\n .filter(k => paramKeyIsPublic(k))\n .map(k => stringifySingleParamUniquely(k, p[k]))\n .join(kParamSeparator);\n}\n\nexport function stringifySingleParam(k: string, v: JSONWithUndefined) {\n return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`;\n}\n\nfunction stringifySingleParamUniquely(k: string, v: JSONWithUndefined) {\n return `${k}${kParamKVSeparator}${stringifyParamValueUniquely(v)}`;\n}\n\nfunction stringifySingleParamValue(v: JSONWithUndefined): string {\n const s = stringifyParamValue(v);\n assert(\n !badParamValueChars.test(s),\n `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`\n );\n return s;\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,QAAQ,oBAAoB,CAC3C,SAA4BC,kBAAkB,EAAEC,gBAAgB,QAAQ,oBAAoB;;AAE5F,SAASC,mBAAmB,EAAEC,2BAA2B,QAAQ,uBAAuB;AACxF,SAASC,iBAAiB,EAAEC,eAAe,EAAEC,SAAS,QAAQ,iBAAiB;;AAE/E,OAAO,SAASC,qBAAqB,CAACC,CAAa,EAAEC,WAAW,GAAG,KAAK,EAAU;EAChF,MAAMC,KAAK,GAAGC,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC;EACzBK,MAAM,CAAC,CAAAC,CAAC,KAAIb,gBAAgB,CAACa,CAAC,CAAC,CAAC;EAChCC,GAAG,CAAC,CAAAD,CAAC,KAAIE,oBAAoB,CAACF,CAAC,EAAEN,CAAC,CAACM,CAAC,CAAC,CAAC,CAAC;;EAE1C,IAAIL,WAAW,EAAEC,KAAK,CAACO,IAAI,CAACX,SAAS,CAAC;;EAEtC,OAAOI,KAAK,CAACQ,IAAI,CAACb,eAAe,CAAC;AACpC;;AAEA;AACA;AACA;AACA,OAAO,SAASc,6BAA6B,CAACX,CAAa,EAAU;EACnE,MAAMI,IAAI,GAAGD,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC,CAACY,IAAI,EAAE;EAClC,OAAOR,IAAI;EACRC,MAAM,CAAC,CAAAC,CAAC,KAAIb,gBAAgB,CAACa,CAAC,CAAC,CAAC;EAChCC,GAAG,CAAC,CAAAD,CAAC,KAAIO,4BAA4B,CAACP,CAAC,EAAEN,CAAC,CAACM,CAAC,CAAC,CAAC,CAAC;EAC/CI,IAAI,CAACb,eAAe,CAAC;AAC1B;;AAEA,OAAO,SAASW,oBAAoB,CAACF,CAAS,EAAEQ,CAAoB,EAAE;EACpE,OAAQ,GAAER,CAAE,GAAEV,iBAAkB,GAAEmB,yBAAyB,CAACD,CAAC,CAAE,EAAC;AAClE;;AAEA,SAASD,4BAA4B,CAACP,CAAS,EAAEQ,CAAoB,EAAE;EACrE,OAAQ,GAAER,CAAE,GAAEV,iBAAkB,GAAED,2BAA2B,CAACmB,CAAC,CAAE,EAAC;AACpE;;AAEA,SAASC,yBAAyB,CAACD,CAAoB,EAAU;EAC/D,MAAME,CAAC,GAAGtB,mBAAmB,CAACoB,CAAC,CAAC;EAChCvB,MAAM;EACJ,CAACC,kBAAkB,CAACyB,IAAI,CAACD,CAAC,CAAC;EAC1B,+CAA8CxB,kBAAmB,UAASwB,CAAE,EAAC,CAC/E;;EACD,OAAOA,CAAC;AACV"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js
new file mode 100644
index 0000000000..9fa7135cc5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js
@@ -0,0 +1,4 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /** Applies to group parts, test parts, params keys. */export const validQueryPart = /^[a-zA-Z0-9_]+$/;
+//# sourceMappingURL=validQueryPart.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map
new file mode 100644
index 0000000000..3bd6e8e82b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"validQueryPart.js","names":["validQueryPart"],"sources":["../../../../src/common/internal/query/validQueryPart.ts"],"sourcesContent":["/** Applies to group parts, test parts, params keys. */\nexport const validQueryPart = /^[a-zA-Z0-9_]+$/;\n"],"mappings":";AAAA;AAAA,G,CAAA,uDACA,OAAO,MAAMA,cAAc,GAAG,iBAAiB"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js
new file mode 100644
index 0000000000..bff671d204
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js
@@ -0,0 +1,83 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ // Returns the stack trace of an Error, but without the extra boilerplate at the bottom
+// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging.
+export function extractImportantStackTrace(e) {let stack = e.stack;if (!stack) {
+ return '';
+ }
+ const redundantMessage = 'Error: ' + e.message + '\n';
+ if (stack.startsWith(redundantMessage)) {
+ stack = stack.substring(redundantMessage.length);
+ }
+
+ const lines = stack.split('\n');
+ for (let i = lines.length - 1; i >= 0; --i) {
+ const line = lines[i];
+ if (line.indexOf('.spec.') !== -1) {
+ return lines.slice(0, i + 1).join('\n');
+ }
+ }
+ return stack;
+}
+
+// *** Examples ***
+//
+// Node fail()
+// > Error:
+// > at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30)
+// > at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7)
+// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
+// x at processTicksAndRejections (internal/process/task_queues.js:86:5)
+//
+// Node throw
+// > Error: hello
+// > at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11)
+// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
+// x at processTicksAndRejections (internal/process/task_queues.js:86:5)
+//
+// Firefox fail()
+// > fail@http://localhost:8080/out/framework/logger.js:104:30
+// > expect@http://localhost:8080/out/framework/default_fixture.js:59:16
+// > @http://localhost:8080/out/unittests/util.spec.js:35:5
+// x run@http://localhost:8080/out/framework/test_group.js:119:18
+//
+// Firefox throw
+// > @http://localhost:8080/out/unittests/test_group.spec.js:48:11
+// x run@http://localhost:8080/out/framework/test_group.js:119:18
+//
+// Safari fail()
+// > fail@http://localhost:8080/out/framework/logger.js:104:39
+// > expect@http://localhost:8080/out/framework/default_fixture.js:59:20
+// > http://localhost:8080/out/unittests/util.spec.js:35:11
+// x http://localhost:8080/out/framework/test_group.js:119:20
+// x asyncFunctionResume@[native code]
+// x [native code]
+// x promiseReactionJob@[native code]
+//
+// Safari throw
+// > http://localhost:8080/out/unittests/test_group.spec.js:48:20
+// x http://localhost:8080/out/framework/test_group.js:119:20
+// x asyncFunctionResume@[native code]
+// x [native code]
+// x promiseReactionJob@[native code]
+//
+// Chrome fail()
+// x Error
+// x at CaseRecorder.fail (http://localhost:8080/out/framework/logger.js:104:30)
+// x at DefaultFixture.expect (http://localhost:8080/out/framework/default_fixture.js:59:16)
+// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5)
+// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)
+// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)
+// x at async http://localhost:8080/out/runtime/standalone.js:102:7
+//
+// Chrome throw
+// x Error: hello
+// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
+// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)"
+// x at async Promise.all (index 0)
+// x at async TestGroupTest.run (http://localhost:8080/out/unittests/test_group_test.js:6:5)
+// x at async RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:53:15)
+// x at async RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:7)
+// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)
+// x at async http://localhost:8080/out/runtime/standalone.js:102:7
+//# sourceMappingURL=stack.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map
new file mode 100644
index 0000000000..399d289119
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"stack.js","names":["extractImportantStackTrace","e","stack","redundantMessage","message","startsWith","substring","length","lines","split","i","line","indexOf","slice","join"],"sources":["../../../src/common/internal/stack.ts"],"sourcesContent":["// Returns the stack trace of an Error, but without the extra boilerplate at the bottom\n// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging.\nexport function extractImportantStackTrace(e: Error): string {\n let stack = e.stack;\n if (!stack) {\n return '';\n }\n const redundantMessage = 'Error: ' + e.message + '\\n';\n if (stack.startsWith(redundantMessage)) {\n stack = stack.substring(redundantMessage.length);\n }\n\n const lines = stack.split('\\n');\n for (let i = lines.length - 1; i >= 0; --i) {\n const line = lines[i];\n if (line.indexOf('.spec.') !== -1) {\n return lines.slice(0, i + 1).join('\\n');\n }\n }\n return stack;\n}\n\n// *** Examples ***\n//\n// Node fail()\n// > Error:\n// > at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30)\n// > at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7)\n// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)\n// x at processTicksAndRejections (internal/process/task_queues.js:86:5)\n//\n// Node throw\n// > Error: hello\n// > at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11)\n// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)\n// x at processTicksAndRejections (internal/process/task_queues.js:86:5)\n//\n// Firefox fail()\n// > fail@http://localhost:8080/out/framework/logger.js:104:30\n// > expect@http://localhost:8080/out/framework/default_fixture.js:59:16\n// > @http://localhost:8080/out/unittests/util.spec.js:35:5\n// x run@http://localhost:8080/out/framework/test_group.js:119:18\n//\n// Firefox throw\n// > @http://localhost:8080/out/unittests/test_group.spec.js:48:11\n// x run@http://localhost:8080/out/framework/test_group.js:119:18\n//\n// Safari fail()\n// > fail@http://localhost:8080/out/framework/logger.js:104:39\n// > expect@http://localhost:8080/out/framework/default_fixture.js:59:20\n// > http://localhost:8080/out/unittests/util.spec.js:35:11\n// x http://localhost:8080/out/framework/test_group.js:119:20\n// x asyncFunctionResume@[native code]\n// x [native code]\n// x promiseReactionJob@[native code]\n//\n// Safari throw\n// > http://localhost:8080/out/unittests/test_group.spec.js:48:20\n// x http://localhost:8080/out/framework/test_group.js:119:20\n// x asyncFunctionResume@[native code]\n// x [native code]\n// x promiseReactionJob@[native code]\n//\n// Chrome fail()\n// x Error\n// x at CaseRecorder.fail (http://localhost:8080/out/framework/logger.js:104:30)\n// x at DefaultFixture.expect (http://localhost:8080/out/framework/default_fixture.js:59:16)\n// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5)\n// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)\n// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)\n// x at async http://localhost:8080/out/runtime/standalone.js:102:7\n//\n// Chrome throw\n// x Error: hello\n// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)\n// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)\"\n// x at async Promise.all (index 0)\n// x at async TestGroupTest.run (http://localhost:8080/out/unittests/test_group_test.js:6:5)\n// x at async RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:53:15)\n// x at async RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:7)\n// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)\n// x at async http://localhost:8080/out/runtime/standalone.js:102:7\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA,OAAO,SAASA,0BAA0B,CAACC,CAAQ,EAAU,CAC3D,IAAIC,KAAK,GAAGD,CAAC,CAACC,KAAK,CACnB,IAAI,CAACA,KAAK,EAAE;IACV,OAAO,EAAE;EACX;EACA,MAAMC,gBAAgB,GAAG,SAAS,GAAGF,CAAC,CAACG,OAAO,GAAG,IAAI;EACrD,IAAIF,KAAK,CAACG,UAAU,CAACF,gBAAgB,CAAC,EAAE;IACtCD,KAAK,GAAGA,KAAK,CAACI,SAAS,CAACH,gBAAgB,CAACI,MAAM,CAAC;EAClD;;EAEA,MAAMC,KAAK,GAAGN,KAAK,CAACO,KAAK,CAAC,IAAI,CAAC;EAC/B,KAAK,IAAIC,CAAC,GAAGF,KAAK,CAACD,MAAM,GAAG,CAAC,EAAEG,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;IAC1C,MAAMC,IAAI,GAAGH,KAAK,CAACE,CAAC,CAAC;IACrB,IAAIC,IAAI,CAACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE;MACjC,OAAOJ,KAAK,CAACK,KAAK,CAAC,CAAC,EAAEH,CAAC,GAAG,CAAC,CAAC,CAACI,IAAI,CAAC,IAAI,CAAC;IACzC;EACF;EACA,OAAOZ,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js
new file mode 100644
index 0000000000..74eb775c60
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js
@@ -0,0 +1,647 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import {
+SkipTestCase,
+
+UnexpectedPassError } from
+'../framework/fixture.js';
+import {
+
+builderIterateCasesWithSubcases,
+kUnitCaseParamsBuilder } from
+
+
+'../framework/params_builder.js';
+import { globalTestConfig } from '../framework/test_config.js';
+
+import { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';
+import { extractPublicParams, mergeParams } from '../internal/params_utils.js';
+import { compareQueries, Ordering } from '../internal/query/compare.js';
+import { TestQuerySingleCase } from '../internal/query/query.js';
+import { kPathSeparator } from '../internal/query/separators.js';
+import {
+stringifyPublicParams,
+stringifyPublicParamsUniquely } from
+'../internal/query/stringify_params.js';
+import { validQueryPart } from '../internal/query/validQueryPart.js';
+import { assert, unreachable } from '../util/util.js';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+export function makeTestGroup(
+fixture)
+{
+ return new TestGroup(fixture);
+}
+
+// Interfaces for running tests
+
+
+
+
+
+
+
+
+
+
+
+export function makeTestGroupForUnitTesting(
+fixture)
+{
+ return new TestGroup(fixture);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+export class TestGroup
+{
+
+ seen = new Set();
+ tests = [];
+
+ constructor(fixture) {
+ this.fixture = fixture;
+ }
+
+ iterate() {
+ return this.tests;
+ }
+
+ checkName(name) {
+ assert(
+ // Shouldn't happen due to the rule above. Just makes sure that treating
+ // unencoded strings as encoded strings is OK.
+ name === decodeURIComponent(name),
+ `Not decodeURIComponent-idempotent: ${name} !== ${decodeURIComponent(name)}`);
+
+ assert(!this.seen.has(name), `Duplicate test name: ${name}`);
+
+ this.seen.add(name);
+ }
+
+ test(name) {
+ const testCreationStack = new Error(`Test created: ${name}`);
+
+ this.checkName(name);
+
+ const parts = name.split(kPathSeparator);
+ for (const p of parts) {
+ assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`);
+ }
+
+ const test = new TestBuilder(parts, this.fixture, testCreationStack);
+ this.tests.push(test);
+ return test;
+ }
+
+ validate() {
+ for (const test of this.tests) {
+ test.validate();
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class TestBuilder {
+
+
+
+
+
+
+
+
+ testCases = undefined;
+ batchSize = 0;
+
+ constructor(testPath, fixture, testCreationStack) {
+ this.testPath = testPath;
+ this.isUnimplemented = false;
+ this.fixture = fixture;
+ this.testCreationStack = testCreationStack;
+ }
+
+ desc(description) {
+ this.description = description.trim();
+ return this;
+ }
+
+ specURL(url) {
+ return this;
+ }
+
+ beforeAllSubcases(fn) {
+ assert(this.beforeFn === undefined);
+ this.beforeFn = fn;
+ return this;
+ }
+
+ fn(fn) {
+
+ // MAINTENANCE_TODO: add "TODO" if there's no description? (and make sure it only ends up on
+ // actual tests, not on test parents in the tree, which is what happens if you do it here, not
+ // sure why)
+ assert(this.testFn === undefined);
+ this.testFn = fn;
+ }
+
+ batch(b) {
+ this.batchSize = b;
+ return this;
+ }
+
+ unimplemented() {
+ assert(this.testFn === undefined);
+
+ this.description =
+ (this.description ? this.description + '\n\n' : '') + 'TODO: .unimplemented()';
+ this.isUnimplemented = true;
+
+ this.testFn = () => {
+ throw new SkipTestCase('test unimplemented');
+ };
+ }
+
+ validate() {
+ const testPathString = this.testPath.join(kPathSeparator);
+ assert(this.testFn !== undefined, () => {
+ let s = `Test is missing .fn(): ${testPathString}`;
+ if (this.testCreationStack.stack) {
+ s += `\n-> test created at:\n${this.testCreationStack.stack}`;
+ }
+ return s;
+ });
+
+ if (this.testCases === undefined) {
+ return;
+ }
+
+ const seen = new Set();
+ for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {
+ for (const subcaseParams of subcases ?? [{}]) {
+ const params = mergeParams(caseParams, subcaseParams);
+ assert(this.batchSize === 0 || !('batch__' in params));
+
+ // stringifyPublicParams also checks for invalid params values
+ const testcaseString = stringifyPublicParams(params);
+
+ // A (hopefully) unique representation of a params value.
+ const testcaseStringUnique = stringifyPublicParamsUniquely(params);
+ assert(
+ !seen.has(testcaseStringUnique),
+ `Duplicate public test case params for test ${testPathString}: ${testcaseString}`);
+
+ seen.add(testcaseStringUnique);
+ }
+ }
+ }
+
+ params(
+ cases)
+ {
+ assert(this.testCases === undefined, 'test case is already parameterized');
+ if (cases instanceof Function) {
+ this.testCases = cases(kUnitCaseParamsBuilder);
+ } else {
+ this.testCases = cases;
+ }
+ return this;
+ }
+
+ paramsSimple(cases) {
+ assert(this.testCases === undefined, 'test case is already parameterized');
+ this.testCases = kUnitCaseParamsBuilder.combineWithParams(cases);
+ return this;
+ }
+
+ paramsSubcasesOnly(
+ subcases)
+ {
+ if (subcases instanceof Function) {
+ return this.params(subcases(kUnitCaseParamsBuilder.beginSubcases()));
+ } else {
+ return this.params(kUnitCaseParamsBuilder.beginSubcases().combineWithParams(subcases));
+ }
+ }
+
+ *iterate() {
+ assert(this.testFn !== undefined, 'No test function (.fn()) for test');
+ this.testCases ??= kUnitCaseParamsBuilder;
+ for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {
+ if (this.batchSize === 0 || subcases === undefined) {
+ yield new RunCaseSpecific(
+ this.testPath,
+ caseParams,
+ this.isUnimplemented,
+ subcases,
+ this.fixture,
+ this.testFn,
+ this.beforeFn,
+ this.testCreationStack);
+
+ } else {
+ const subcaseArray = Array.from(subcases);
+ if (subcaseArray.length <= this.batchSize) {
+ yield new RunCaseSpecific(
+ this.testPath,
+ caseParams,
+ this.isUnimplemented,
+ subcaseArray,
+ this.fixture,
+ this.testFn,
+ this.beforeFn,
+ this.testCreationStack);
+
+ } else {
+ for (let i = 0; i < subcaseArray.length; i = i + this.batchSize) {
+ yield new RunCaseSpecific(
+ this.testPath,
+ { ...caseParams, batch__: i / this.batchSize },
+ this.isUnimplemented,
+ subcaseArray.slice(i, Math.min(subcaseArray.length, i + this.batchSize)),
+ this.fixture,
+ this.testFn,
+ this.beforeFn,
+ this.testCreationStack);
+
+ }
+ }
+ }
+ }
+ }
+}
+
+class RunCaseSpecific {
+
+
+
+
+
+
+
+
+
+
+ constructor(
+ testPath,
+ params,
+ isUnimplemented,
+ subcases,
+ fixture,
+ fn,
+ beforeFn,
+ testCreationStack)
+ {
+ this.id = { test: testPath, params: extractPublicParams(params) };
+ this.isUnimplemented = isUnimplemented;
+ this.params = params;
+ this.subcases = subcases;
+ this.fixture = fixture;
+ this.fn = fn;
+ this.beforeFn = beforeFn;
+ this.testCreationStack = testCreationStack;
+ }
+
+ async runTest(
+ rec,
+ sharedState,
+ params,
+ throwSkip,
+ expectedStatus)
+ {
+ try {
+ rec.beginSubCase();
+ if (expectedStatus === 'skip') {
+ throw new SkipTestCase('Skipped by expectations');
+ }
+
+ const inst = new this.fixture(sharedState, rec, params);
+ try {
+ await inst.init();
+ await this.fn(inst);
+ } finally {
+ // Runs as long as constructor succeeded, even if initialization or the test failed.
+ await inst.finalize();
+ }
+ } catch (ex) {
+ // There was an exception from constructor, init, test, or finalize.
+ // An error from init or test may have been a SkipTestCase.
+ // An error from finalize may have been an eventualAsyncExpectation failure
+ // or unexpected validation/OOM error from the GPUDevice.
+ if (throwSkip && ex instanceof SkipTestCase) {
+ throw ex;
+ }
+ rec.threw(ex);
+ } finally {
+ try {
+ rec.endSubCase(expectedStatus);
+ } catch (ex) {
+ assert(ex instanceof UnexpectedPassError);
+ ex.message = `Testcase passed unexpectedly.`;
+ ex.stack = this.testCreationStack.stack;
+ rec.warn(ex);
+ }
+ }
+ }
+
+ async run(
+ rec,
+ selfQuery,
+ expectations)
+ {
+ const getExpectedStatus = (selfQueryWithSubParams) => {
+ let didSeeFail = false;
+ for (const exp of expectations) {
+ const ordering = compareQueries(exp.query, selfQueryWithSubParams);
+ if (ordering === Ordering.Unordered || ordering === Ordering.StrictSubset) {
+ continue;
+ }
+
+ switch (exp.expectation) {
+ // Skip takes precedence. If there is any expectation indicating a skip,
+ // signal it immediately.
+ case 'skip':
+ return 'skip';
+ case 'fail':
+ // Otherwise, indicate that we might expect a failure.
+ didSeeFail = true;
+ break;
+ default:
+ unreachable();}
+
+ }
+ return didSeeFail ? 'fail' : 'pass';
+ };
+
+ const { testHeartbeatCallback, maxSubcasesInFlight } = globalTestConfig;
+ try {
+ rec.start();
+ const sharedState = this.fixture.MakeSharedState(this.params);
+ try {
+ await sharedState.init();
+ if (this.beforeFn) {
+ await this.beforeFn(sharedState);
+ }
+ await sharedState.postInit();
+ testHeartbeatCallback();
+
+ let allPreviousSubcasesFinalizedPromise = Promise.resolve();
+ if (this.subcases) {
+ let totalCount = 0;
+ let skipCount = 0;
+
+ // If there are too many subcases in flight, starting the next subcase will register
+ // `resolvePromiseBlockingSubcase` and wait until `subcaseFinishedCallback` is called.
+ let subcasesInFlight = 0;
+ let resolvePromiseBlockingSubcase = undefined;
+ const subcaseFinishedCallback = () => {
+ subcasesInFlight -= 1;
+ // If there is any subcase waiting on a previous subcase to finish,
+ // unblock it now, and clear the resolve callback.
+ if (resolvePromiseBlockingSubcase) {
+ resolvePromiseBlockingSubcase();
+ resolvePromiseBlockingSubcase = undefined;
+ }
+ };
+
+ for (const subParams of this.subcases) {
+ // Make a recorder that will defer all calls until `allPreviousSubcasesFinalizedPromise`
+ // resolves. Waiting on `allPreviousSubcasesFinalizedPromise` ensures that
+ // logs from all the previous subcases have been flushed before flushing new logs.
+ const subcasePrefix = 'subcase: ' + stringifyPublicParams(subParams);
+ const subRec = new Proxy(rec, {
+ get: (target, k) => {
+ const prop = TestCaseRecorder.prototype[k];
+ if (typeof prop === 'function') {
+ testHeartbeatCallback();
+ return function (...args) {
+ void allPreviousSubcasesFinalizedPromise.then(() => {
+ // Prepend the subcase name to all error messages.
+ for (const arg of args) {
+ if (arg instanceof Error) {
+ try {
+ arg.message = subcasePrefix + '\n' + arg.message;
+ } catch {
+ // If that fails (e.g. on DOMException), try to put it in the stack:
+ let stack = subcasePrefix;
+ if (arg.stack) stack += '\n' + arg.stack;
+ try {
+ arg.stack = stack;
+ } catch {
+
+ // If that fails too, just silence it.
+ }}
+ }
+ }
+
+
+ const rv = prop.apply(target, args);
+ // Because this proxy executes functions in a deferred manner,
+ // it should never be used for functions that need to return a value.
+ assert(rv === undefined);
+ });
+ };
+ }
+ return prop;
+ }
+ });
+
+ const params = mergeParams(this.params, subParams);
+ const subcaseQuery = new TestQuerySingleCase(
+ selfQuery.suite,
+ selfQuery.filePathParts,
+ selfQuery.testPathParts,
+ params);
+
+
+ // Limit the maximum number of subcases in flight.
+ if (subcasesInFlight >= maxSubcasesInFlight) {
+ await new Promise((resolve) => {
+ // There should only be one subcase waiting at a time.
+ assert(resolvePromiseBlockingSubcase === undefined);
+ resolvePromiseBlockingSubcase = resolve;
+ });
+ }
+
+ subcasesInFlight += 1;
+ // Runs async without waiting so that subsequent subcases can start.
+ // All finalization steps will be waited on at the end of the testcase.
+ const finalizePromise = this.runTest(
+ subRec,
+ sharedState,
+ params,
+ /* throwSkip */true,
+ getExpectedStatus(subcaseQuery)).
+
+ then(() => {
+ subRec.info(new Error('OK'));
+ }).
+ catch((ex) => {
+ if (ex instanceof SkipTestCase) {
+ // Convert SkipTestCase to info messages
+ ex.message = 'subcase skipped: ' + ex.message;
+ subRec.info(ex);
+ ++skipCount;
+ } else {
+ // Since we are catching all error inside runTest(), this should never happen
+ subRec.threw(ex);
+ }
+ }).
+ finally(subcaseFinishedCallback);
+
+ allPreviousSubcasesFinalizedPromise = allPreviousSubcasesFinalizedPromise.then(
+ () => finalizePromise);
+
+ ++totalCount;
+ }
+
+ // Wait for all subcases to finalize and report their results.
+ await allPreviousSubcasesFinalizedPromise;
+
+ if (skipCount === totalCount) {
+ rec.skipped(new SkipTestCase('all subcases were skipped'));
+ }
+ } else {
+ await this.runTest(
+ rec,
+ sharedState,
+ this.params,
+ /* throwSkip */false,
+ getExpectedStatus(selfQuery));
+
+ }
+ } finally {
+ testHeartbeatCallback();
+ // Runs as long as the shared state constructor succeeded, even if initialization or a test failed.
+ await sharedState.finalize();
+ testHeartbeatCallback();
+ }
+ } catch (ex) {
+ // There was an exception from sharedState/fixture constructor, init, beforeFn, or test.
+ // An error from beforeFn may have been SkipTestCase.
+ // An error from finalize may have been an eventualAsyncExpectation failure
+ // or unexpected validation/OOM error from the GPUDevice.
+ rec.threw(ex);
+ } finally {
+ rec.finish();
+ }
+ }
+}
+//# sourceMappingURL=test_group.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map
new file mode 100644
index 0000000000..f45df9e09c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"test_group.js","names":["SkipTestCase","UnexpectedPassError","builderIterateCasesWithSubcases","kUnitCaseParamsBuilder","globalTestConfig","TestCaseRecorder","extractPublicParams","mergeParams","compareQueries","Ordering","TestQuerySingleCase","kPathSeparator","stringifyPublicParams","stringifyPublicParamsUniquely","validQueryPart","assert","unreachable","makeTestGroup","fixture","TestGroup","makeTestGroupForUnitTesting","seen","Set","tests","constructor","iterate","checkName","name","decodeURIComponent","has","add","test","testCreationStack","Error","parts","split","p","TestBuilder","push","validate","testCases","undefined","batchSize","testPath","isUnimplemented","desc","description","trim","specURL","url","beforeAllSubcases","fn","beforeFn","testFn","batch","b","unimplemented","testPathString","join","s","stack","caseParams","subcases","subcaseParams","params","testcaseString","testcaseStringUnique","cases","Function","paramsSimple","combineWithParams","paramsSubcasesOnly","beginSubcases","RunCaseSpecific","subcaseArray","Array","from","length","i","batch__","slice","Math","min","id","runTest","rec","sharedState","throwSkip","expectedStatus","beginSubCase","inst","init","finalize","ex","threw","endSubCase","message","warn","run","selfQuery","expectations","getExpectedStatus","selfQueryWithSubParams","didSeeFail","exp","ordering","query","Unordered","StrictSubset","expectation","testHeartbeatCallback","maxSubcasesInFlight","start","MakeSharedState","postInit","allPreviousSubcasesFinalizedPromise","Promise","resolve","totalCount","skipCount","subcasesInFlight","resolvePromiseBlockingSubcase","subcaseFinishedCallback","subParams","subcasePrefix","subRec","Proxy","get","target","k","prop","prototype","args","then","arg","rv","apply","subcaseQuery","suite","filePathParts","testPathParts","finalizePromise","info","catch","finally","skipped","finish"],"sources":["../../../src/common/internal/test_group.ts"],"sourcesContent":["import {\n Fixture,\n SubcaseBatchState,\n SkipTestCase,\n TestParams,\n UnexpectedPassError,\n} from '../framework/fixture.js';\nimport {\n CaseParamsBuilder,\n builderIterateCasesWithSubcases,\n kUnitCaseParamsBuilder,\n ParamsBuilderBase,\n SubcaseParamsBuilder,\n} from '../framework/params_builder.js';\nimport { globalTestConfig } from '../framework/test_config.js';\nimport { Expectation } from '../internal/logging/result.js';\nimport { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';\nimport { extractPublicParams, Merged, mergeParams } from '../internal/params_utils.js';\nimport { compareQueries, Ordering } from '../internal/query/compare.js';\nimport { TestQuerySingleCase, TestQueryWithExpectation } from '../internal/query/query.js';\nimport { kPathSeparator } from '../internal/query/separators.js';\nimport {\n stringifyPublicParams,\n stringifyPublicParamsUniquely,\n} from '../internal/query/stringify_params.js';\nimport { validQueryPart } from '../internal/query/validQueryPart.js';\nimport { assert, unreachable } from '../util/util.js';\n\nexport type RunFn = (\n rec: TestCaseRecorder,\n expectations?: TestQueryWithExpectation[]\n) => Promise<void>;\n\nexport interface TestCaseID {\n readonly test: readonly string[];\n readonly params: TestParams;\n}\n\nexport interface RunCase {\n readonly id: TestCaseID;\n readonly isUnimplemented: boolean;\n run(\n rec: TestCaseRecorder,\n selfQuery: TestQuerySingleCase,\n expectations: TestQueryWithExpectation[]\n ): Promise<void>;\n}\n\n// Interface for defining tests\nexport interface TestGroupBuilder<S extends SubcaseBatchState, F extends Fixture<S>> {\n test(name: string): TestBuilderWithName<S, F>;\n}\nexport function makeTestGroup<S extends SubcaseBatchState, F extends Fixture<S>>(\n fixture: FixtureClass<S, F>\n): TestGroupBuilder<S, F> {\n return new TestGroup((fixture as unknown) as FixtureClass);\n}\n\n// Interfaces for running tests\nexport interface IterableTestGroup {\n iterate(): Iterable<IterableTest>;\n validate(): void;\n}\nexport interface IterableTest {\n testPath: string[];\n description: string | undefined;\n readonly testCreationStack: Error;\n iterate(): Iterable<RunCase>;\n}\n\nexport function makeTestGroupForUnitTesting<F extends Fixture>(\n fixture: FixtureClass<SubcaseBatchState, F>\n): TestGroup<SubcaseBatchState, F> {\n return new TestGroup(fixture);\n}\n\nexport type FixtureClass<\n S extends SubcaseBatchState = SubcaseBatchState,\n F extends Fixture<S> = Fixture<S>\n> = {\n new (sharedState: S, log: TestCaseRecorder, params: TestParams): F;\n MakeSharedState(params: TestParams): S;\n};\ntype TestFn<F extends Fixture, P extends {}> = (t: F & { params: P }) => Promise<void> | void;\ntype BeforeAllSubcasesFn<S extends SubcaseBatchState, P extends {}> = (\n s: S & { params: P }\n) => Promise<void> | void;\n\nexport class TestGroup<S extends SubcaseBatchState, F extends Fixture<S>>\n implements TestGroupBuilder<S, F> {\n private fixture: FixtureClass;\n private seen: Set<string> = new Set();\n private tests: Array<TestBuilder<S, F>> = [];\n\n constructor(fixture: FixtureClass) {\n this.fixture = fixture;\n }\n\n iterate(): Iterable<IterableTest> {\n return this.tests;\n }\n\n private checkName(name: string): void {\n assert(\n // Shouldn't happen due to the rule above. Just makes sure that treating\n // unencoded strings as encoded strings is OK.\n name === decodeURIComponent(name),\n `Not decodeURIComponent-idempotent: ${name} !== ${decodeURIComponent(name)}`\n );\n assert(!this.seen.has(name), `Duplicate test name: ${name}`);\n\n this.seen.add(name);\n }\n\n test(name: string): TestBuilderWithName<S, F> {\n const testCreationStack = new Error(`Test created: ${name}`);\n\n this.checkName(name);\n\n const parts = name.split(kPathSeparator);\n for (const p of parts) {\n assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`);\n }\n\n const test = new TestBuilder(parts, this.fixture, testCreationStack);\n this.tests.push(test);\n return (test as unknown) as TestBuilderWithName<S, F>;\n }\n\n validate(): void {\n for (const test of this.tests) {\n test.validate();\n }\n }\n}\n\ninterface TestBuilderWithName<S extends SubcaseBatchState, F extends Fixture<S>>\n extends TestBuilderWithParams<S, F, {}, {}> {\n desc(description: string): this;\n /**\n * A noop function to associate a test with the relevant part of the specification.\n *\n * @param url a link to the spec where test is extracted from.\n */\n specURL(url: string): this;\n /**\n * Parameterize the test, generating multiple cases, each possibly having subcases.\n *\n * The `unit` value passed to the `cases` callback is an immutable constant\n * `CaseParamsBuilder<{}>` representing the \"unit\" builder `[ {} ]`,\n * provided for convenience. The non-callback overload can be used if `unit` is not needed.\n */\n params<CaseP extends {}, SubcaseP extends {}>(\n cases: (unit: CaseParamsBuilder<{}>) => ParamsBuilderBase<CaseP, SubcaseP>\n ): TestBuilderWithParams<S, F, CaseP, SubcaseP>;\n /**\n * Parameterize the test, generating multiple cases, each possibly having subcases.\n *\n * Use the callback overload of this method if a \"unit\" builder is needed.\n */\n params<CaseP extends {}, SubcaseP extends {}>(\n cases: ParamsBuilderBase<CaseP, SubcaseP>\n ): TestBuilderWithParams<S, F, CaseP, SubcaseP>;\n\n /**\n * Parameterize the test, generating multiple cases, without subcases.\n */\n paramsSimple<P extends {}>(cases: Iterable<P>): TestBuilderWithParams<S, F, P, {}>;\n\n /**\n * Parameterize the test, generating one case with multiple subcases.\n */\n paramsSubcasesOnly<P extends {}>(subcases: Iterable<P>): TestBuilderWithParams<S, F, {}, P>;\n /**\n * Parameterize the test, generating one case with multiple subcases.\n *\n * The `unit` value passed to the `subcases` callback is an immutable constant\n * `SubcaseParamsBuilder<{}>`, with one empty case `{}` and one empty subcase `{}`.\n */\n paramsSubcasesOnly<P extends {}>(\n subcases: (unit: SubcaseParamsBuilder<{}, {}>) => SubcaseParamsBuilder<{}, P>\n ): TestBuilderWithParams<S, F, {}, P>;\n}\n\ninterface TestBuilderWithParams<\n S extends SubcaseBatchState,\n F extends Fixture<S>,\n CaseP extends {},\n SubcaseP extends {}\n> {\n /**\n * Limit subcases to a maximum number of per testcase.\n * @param b the maximum number of subcases per testcase.\n *\n * If the number of subcases exceeds `b`, add an internal\n * numeric, incrementing `batch__` param to split subcases\n * into groups of at most `b` subcases.\n */\n batch(b: number): this;\n /**\n * Run a function on shared subcase batch state before each\n * batch of subcases.\n * @param fn the function to run. It is called with the test\n * fixture's shared subcase batch state.\n *\n * Generally, this function should be careful to avoid mutating\n * any state on the shared subcase batch state which could result\n * in unexpected order-dependent test behavior.\n */\n beforeAllSubcases(fn: BeforeAllSubcasesFn<S, CaseP>): this;\n /**\n * Set the test function.\n * @param fn the test function.\n */\n fn(fn: TestFn<F, Merged<CaseP, SubcaseP>>): void;\n /**\n * Mark the test as unimplemented.\n */\n unimplemented(): void;\n}\n\nclass TestBuilder<S extends SubcaseBatchState, F extends Fixture> {\n readonly testPath: string[];\n isUnimplemented: boolean;\n description: string | undefined;\n readonly testCreationStack: Error;\n\n private readonly fixture: FixtureClass;\n private testFn: TestFn<Fixture, {}> | undefined;\n private beforeFn: BeforeAllSubcasesFn<SubcaseBatchState, {}> | undefined;\n private testCases?: ParamsBuilderBase<{}, {}> = undefined;\n private batchSize: number = 0;\n\n constructor(testPath: string[], fixture: FixtureClass, testCreationStack: Error) {\n this.testPath = testPath;\n this.isUnimplemented = false;\n this.fixture = fixture;\n this.testCreationStack = testCreationStack;\n }\n\n desc(description: string): this {\n this.description = description.trim();\n return this;\n }\n\n specURL(url: string): this {\n return this;\n }\n\n beforeAllSubcases(fn: BeforeAllSubcasesFn<SubcaseBatchState, {}>): this {\n assert(this.beforeFn === undefined);\n this.beforeFn = fn;\n return this;\n }\n\n fn(fn: TestFn<Fixture, {}>): void {\n // eslint-disable-next-line no-warning-comments\n // MAINTENANCE_TODO: add \"TODO\" if there's no description? (and make sure it only ends up on\n // actual tests, not on test parents in the tree, which is what happens if you do it here, not\n // sure why)\n assert(this.testFn === undefined);\n this.testFn = fn;\n }\n\n batch(b: number): this {\n this.batchSize = b;\n return this;\n }\n\n unimplemented(): void {\n assert(this.testFn === undefined);\n\n this.description =\n (this.description ? this.description + '\\n\\n' : '') + 'TODO: .unimplemented()';\n this.isUnimplemented = true;\n\n this.testFn = () => {\n throw new SkipTestCase('test unimplemented');\n };\n }\n\n validate(): void {\n const testPathString = this.testPath.join(kPathSeparator);\n assert(this.testFn !== undefined, () => {\n let s = `Test is missing .fn(): ${testPathString}`;\n if (this.testCreationStack.stack) {\n s += `\\n-> test created at:\\n${this.testCreationStack.stack}`;\n }\n return s;\n });\n\n if (this.testCases === undefined) {\n return;\n }\n\n const seen = new Set<string>();\n for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {\n for (const subcaseParams of subcases ?? [{}]) {\n const params = mergeParams(caseParams, subcaseParams);\n assert(this.batchSize === 0 || !('batch__' in params));\n\n // stringifyPublicParams also checks for invalid params values\n const testcaseString = stringifyPublicParams(params);\n\n // A (hopefully) unique representation of a params value.\n const testcaseStringUnique = stringifyPublicParamsUniquely(params);\n assert(\n !seen.has(testcaseStringUnique),\n `Duplicate public test case params for test ${testPathString}: ${testcaseString}`\n );\n seen.add(testcaseStringUnique);\n }\n }\n }\n\n params(\n cases: ((unit: CaseParamsBuilder<{}>) => ParamsBuilderBase<{}, {}>) | ParamsBuilderBase<{}, {}>\n ): TestBuilder<S, F> {\n assert(this.testCases === undefined, 'test case is already parameterized');\n if (cases instanceof Function) {\n this.testCases = cases(kUnitCaseParamsBuilder);\n } else {\n this.testCases = cases;\n }\n return this;\n }\n\n paramsSimple(cases: Iterable<{}>): TestBuilder<S, F> {\n assert(this.testCases === undefined, 'test case is already parameterized');\n this.testCases = kUnitCaseParamsBuilder.combineWithParams(cases);\n return this;\n }\n\n paramsSubcasesOnly(\n subcases: Iterable<{}> | ((unit: SubcaseParamsBuilder<{}, {}>) => SubcaseParamsBuilder<{}, {}>)\n ): TestBuilder<S, F> {\n if (subcases instanceof Function) {\n return this.params(subcases(kUnitCaseParamsBuilder.beginSubcases()));\n } else {\n return this.params(kUnitCaseParamsBuilder.beginSubcases().combineWithParams(subcases));\n }\n }\n\n *iterate(): IterableIterator<RunCase> {\n assert(this.testFn !== undefined, 'No test function (.fn()) for test');\n this.testCases ??= kUnitCaseParamsBuilder;\n for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {\n if (this.batchSize === 0 || subcases === undefined) {\n yield new RunCaseSpecific(\n this.testPath,\n caseParams,\n this.isUnimplemented,\n subcases,\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n } else {\n const subcaseArray = Array.from(subcases);\n if (subcaseArray.length <= this.batchSize) {\n yield new RunCaseSpecific(\n this.testPath,\n caseParams,\n this.isUnimplemented,\n subcaseArray,\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n } else {\n for (let i = 0; i < subcaseArray.length; i = i + this.batchSize) {\n yield new RunCaseSpecific(\n this.testPath,\n { ...caseParams, batch__: i / this.batchSize },\n this.isUnimplemented,\n subcaseArray.slice(i, Math.min(subcaseArray.length, i + this.batchSize)),\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n }\n }\n }\n }\n }\n}\n\nclass RunCaseSpecific implements RunCase {\n readonly id: TestCaseID;\n readonly isUnimplemented: boolean;\n\n private readonly params: {};\n private readonly subcases: Iterable<{}> | undefined;\n private readonly fixture: FixtureClass;\n private readonly fn: TestFn<Fixture, {}>;\n private readonly beforeFn?: BeforeAllSubcasesFn<SubcaseBatchState, {}>;\n private readonly testCreationStack: Error;\n\n constructor(\n testPath: string[],\n params: {},\n isUnimplemented: boolean,\n subcases: Iterable<{}> | undefined,\n fixture: FixtureClass,\n fn: TestFn<Fixture, {}>,\n beforeFn: BeforeAllSubcasesFn<SubcaseBatchState, {}> | undefined,\n testCreationStack: Error\n ) {\n this.id = { test: testPath, params: extractPublicParams(params) };\n this.isUnimplemented = isUnimplemented;\n this.params = params;\n this.subcases = subcases;\n this.fixture = fixture;\n this.fn = fn;\n this.beforeFn = beforeFn;\n this.testCreationStack = testCreationStack;\n }\n\n async runTest(\n rec: TestCaseRecorder,\n sharedState: SubcaseBatchState,\n params: TestParams,\n throwSkip: boolean,\n expectedStatus: Expectation\n ): Promise<void> {\n try {\n rec.beginSubCase();\n if (expectedStatus === 'skip') {\n throw new SkipTestCase('Skipped by expectations');\n }\n\n const inst = new this.fixture(sharedState, rec, params);\n try {\n await inst.init();\n await this.fn(inst as Fixture & { params: {} });\n } finally {\n // Runs as long as constructor succeeded, even if initialization or the test failed.\n await inst.finalize();\n }\n } catch (ex) {\n // There was an exception from constructor, init, test, or finalize.\n // An error from init or test may have been a SkipTestCase.\n // An error from finalize may have been an eventualAsyncExpectation failure\n // or unexpected validation/OOM error from the GPUDevice.\n if (throwSkip && ex instanceof SkipTestCase) {\n throw ex;\n }\n rec.threw(ex);\n } finally {\n try {\n rec.endSubCase(expectedStatus);\n } catch (ex) {\n assert(ex instanceof UnexpectedPassError);\n ex.message = `Testcase passed unexpectedly.`;\n ex.stack = this.testCreationStack.stack;\n rec.warn(ex);\n }\n }\n }\n\n async run(\n rec: TestCaseRecorder,\n selfQuery: TestQuerySingleCase,\n expectations: TestQueryWithExpectation[]\n ): Promise<void> {\n const getExpectedStatus = (selfQueryWithSubParams: TestQuerySingleCase) => {\n let didSeeFail = false;\n for (const exp of expectations) {\n const ordering = compareQueries(exp.query, selfQueryWithSubParams);\n if (ordering === Ordering.Unordered || ordering === Ordering.StrictSubset) {\n continue;\n }\n\n switch (exp.expectation) {\n // Skip takes precedence. If there is any expectation indicating a skip,\n // signal it immediately.\n case 'skip':\n return 'skip';\n case 'fail':\n // Otherwise, indicate that we might expect a failure.\n didSeeFail = true;\n break;\n default:\n unreachable();\n }\n }\n return didSeeFail ? 'fail' : 'pass';\n };\n\n const { testHeartbeatCallback, maxSubcasesInFlight } = globalTestConfig;\n try {\n rec.start();\n const sharedState = this.fixture.MakeSharedState(this.params);\n try {\n await sharedState.init();\n if (this.beforeFn) {\n await this.beforeFn(sharedState);\n }\n await sharedState.postInit();\n testHeartbeatCallback();\n\n let allPreviousSubcasesFinalizedPromise: Promise<void> = Promise.resolve();\n if (this.subcases) {\n let totalCount = 0;\n let skipCount = 0;\n\n // If there are too many subcases in flight, starting the next subcase will register\n // `resolvePromiseBlockingSubcase` and wait until `subcaseFinishedCallback` is called.\n let subcasesInFlight = 0;\n let resolvePromiseBlockingSubcase: (() => void) | undefined = undefined;\n const subcaseFinishedCallback = () => {\n subcasesInFlight -= 1;\n // If there is any subcase waiting on a previous subcase to finish,\n // unblock it now, and clear the resolve callback.\n if (resolvePromiseBlockingSubcase) {\n resolvePromiseBlockingSubcase();\n resolvePromiseBlockingSubcase = undefined;\n }\n };\n\n for (const subParams of this.subcases) {\n // Make a recorder that will defer all calls until `allPreviousSubcasesFinalizedPromise`\n // resolves. Waiting on `allPreviousSubcasesFinalizedPromise` ensures that\n // logs from all the previous subcases have been flushed before flushing new logs.\n const subcasePrefix = 'subcase: ' + stringifyPublicParams(subParams);\n const subRec = new Proxy(rec, {\n get: (target, k: keyof TestCaseRecorder) => {\n const prop = TestCaseRecorder.prototype[k];\n if (typeof prop === 'function') {\n testHeartbeatCallback();\n return function (...args: Parameters<typeof prop>) {\n void allPreviousSubcasesFinalizedPromise.then(() => {\n // Prepend the subcase name to all error messages.\n for (const arg of args) {\n if (arg instanceof Error) {\n try {\n arg.message = subcasePrefix + '\\n' + arg.message;\n } catch {\n // If that fails (e.g. on DOMException), try to put it in the stack:\n let stack = subcasePrefix;\n if (arg.stack) stack += '\\n' + arg.stack;\n try {\n arg.stack = stack;\n } catch {\n // If that fails too, just silence it.\n }\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const rv = (prop as any).apply(target, args);\n // Because this proxy executes functions in a deferred manner,\n // it should never be used for functions that need to return a value.\n assert(rv === undefined);\n });\n };\n }\n return prop;\n },\n });\n\n const params = mergeParams(this.params, subParams);\n const subcaseQuery = new TestQuerySingleCase(\n selfQuery.suite,\n selfQuery.filePathParts,\n selfQuery.testPathParts,\n params\n );\n\n // Limit the maximum number of subcases in flight.\n if (subcasesInFlight >= maxSubcasesInFlight) {\n await new Promise<void>(resolve => {\n // There should only be one subcase waiting at a time.\n assert(resolvePromiseBlockingSubcase === undefined);\n resolvePromiseBlockingSubcase = resolve;\n });\n }\n\n subcasesInFlight += 1;\n // Runs async without waiting so that subsequent subcases can start.\n // All finalization steps will be waited on at the end of the testcase.\n const finalizePromise = this.runTest(\n subRec,\n sharedState,\n params,\n /* throwSkip */ true,\n getExpectedStatus(subcaseQuery)\n )\n .then(() => {\n subRec.info(new Error('OK'));\n })\n .catch(ex => {\n if (ex instanceof SkipTestCase) {\n // Convert SkipTestCase to info messages\n ex.message = 'subcase skipped: ' + ex.message;\n subRec.info(ex);\n ++skipCount;\n } else {\n // Since we are catching all error inside runTest(), this should never happen\n subRec.threw(ex);\n }\n })\n .finally(subcaseFinishedCallback);\n\n allPreviousSubcasesFinalizedPromise = allPreviousSubcasesFinalizedPromise.then(\n () => finalizePromise\n );\n ++totalCount;\n }\n\n // Wait for all subcases to finalize and report their results.\n await allPreviousSubcasesFinalizedPromise;\n\n if (skipCount === totalCount) {\n rec.skipped(new SkipTestCase('all subcases were skipped'));\n }\n } else {\n await this.runTest(\n rec,\n sharedState,\n this.params,\n /* throwSkip */ false,\n getExpectedStatus(selfQuery)\n );\n }\n } finally {\n testHeartbeatCallback();\n // Runs as long as the shared state constructor succeeded, even if initialization or a test failed.\n await sharedState.finalize();\n testHeartbeatCallback();\n }\n } catch (ex) {\n // There was an exception from sharedState/fixture constructor, init, beforeFn, or test.\n // An error from beforeFn may have been SkipTestCase.\n // An error from finalize may have been an eventualAsyncExpectation failure\n // or unexpected validation/OOM error from the GPUDevice.\n rec.threw(ex);\n } finally {\n rec.finish();\n }\n }\n}\n"],"mappings":";AAAA;AAAA,GAAA;AAGEA,YAAY;;AAEZC,mBAAmB;AACd,yBAAyB;AAChC;;AAEEC,+BAA+B;AAC/BC,sBAAsB;;;AAGjB,gCAAgC;AACvC,SAASC,gBAAgB,QAAQ,6BAA6B;;AAE9D,SAASC,gBAAgB,QAAQ,2CAA2C;AAC5E,SAASC,mBAAmB,EAAUC,WAAW,QAAQ,6BAA6B;AACtF,SAASC,cAAc,EAAEC,QAAQ,QAAQ,8BAA8B;AACvE,SAASC,mBAAmB,QAAkC,4BAA4B;AAC1F,SAASC,cAAc,QAAQ,iCAAiC;AAChE;AACEC,qBAAqB;AACrBC,6BAA6B;AACxB,uCAAuC;AAC9C,SAASC,cAAc,QAAQ,qCAAqC;AACpE,SAASC,MAAM,EAAEC,WAAW,QAAQ,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BrD,OAAO,SAASC,aAAa;AAC3BC,OAA2B;AACH;EACxB,OAAO,IAAIC,SAAS,CAAED,OAAO,CAA6B;AAC5D;;AAEA;;;;;;;;;;;;AAYA,OAAO,SAASE,2BAA2B;AACzCF,OAA2C;AACV;EACjC,OAAO,IAAIC,SAAS,CAACD,OAAO,CAAC;AAC/B;;;;;;;;;;;;;;AAcA,OAAO,MAAMC;AACuB;;EAE1BE,IAAI,GAAgB,IAAIC,GAAG,EAAE;EAC7BC,KAAK,GAA6B,EAAE;;EAE5CC,WAAW,CAACN,OAAqB,EAAE;IACjC,IAAI,CAACA,OAAO,GAAGA,OAAO;EACxB;;EAEAO,OAAO,GAA2B;IAChC,OAAO,IAAI,CAACF,KAAK;EACnB;;EAEQG,SAAS,CAACC,IAAY,EAAQ;IACpCZ,MAAM;IACJ;IACA;IACAY,IAAI,KAAKC,kBAAkB,CAACD,IAAI,CAAC;IAChC,sCAAqCA,IAAK,QAAOC,kBAAkB,CAACD,IAAI,CAAE,EAAC,CAC7E;;IACDZ,MAAM,CAAC,CAAC,IAAI,CAACM,IAAI,CAACQ,GAAG,CAACF,IAAI,CAAC,EAAG,wBAAuBA,IAAK,EAAC,CAAC;;IAE5D,IAAI,CAACN,IAAI,CAACS,GAAG,CAACH,IAAI,CAAC;EACrB;;EAEAI,IAAI,CAACJ,IAAY,EAA6B;IAC5C,MAAMK,iBAAiB,GAAG,IAAIC,KAAK,CAAE,iBAAgBN,IAAK,EAAC,CAAC;;IAE5D,IAAI,CAACD,SAAS,CAACC,IAAI,CAAC;;IAEpB,MAAMO,KAAK,GAAGP,IAAI,CAACQ,KAAK,CAACxB,cAAc,CAAC;IACxC,KAAK,MAAMyB,CAAC,IAAIF,KAAK,EAAE;MACrBnB,MAAM,CAACD,cAAc,CAACiB,IAAI,CAACK,CAAC,CAAC,EAAG,0BAAyBA,CAAE,gBAAetB,cAAe,EAAC,CAAC;IAC7F;;IAEA,MAAMiB,IAAI,GAAG,IAAIM,WAAW,CAACH,KAAK,EAAE,IAAI,CAAChB,OAAO,EAAEc,iBAAiB,CAAC;IACpE,IAAI,CAACT,KAAK,CAACe,IAAI,CAACP,IAAI,CAAC;IACrB,OAAQA,IAAI;EACd;;EAEAQ,QAAQ,GAAS;IACf,KAAK,MAAMR,IAAI,IAAI,IAAI,CAACR,KAAK,EAAE;MAC7BQ,IAAI,CAACQ,QAAQ,EAAE;IACjB;EACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAMF,WAAW,CAAiD;;;;;;;;;EASxDG,SAAS,GAA+BC,SAAS;EACjDC,SAAS,GAAW,CAAC;;EAE7BlB,WAAW,CAACmB,QAAkB,EAAEzB,OAAqB,EAAEc,iBAAwB,EAAE;IAC/E,IAAI,CAACW,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAACC,eAAe,GAAG,KAAK;IAC5B,IAAI,CAAC1B,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACc,iBAAiB,GAAGA,iBAAiB;EAC5C;;EAEAa,IAAI,CAACC,WAAmB,EAAQ;IAC9B,IAAI,CAACA,WAAW,GAAGA,WAAW,CAACC,IAAI,EAAE;IACrC,OAAO,IAAI;EACb;;EAEAC,OAAO,CAACC,GAAW,EAAQ;IACzB,OAAO,IAAI;EACb;;EAEAC,iBAAiB,CAACC,EAA8C,EAAQ;IACtEpC,MAAM,CAAC,IAAI,CAACqC,QAAQ,KAAKX,SAAS,CAAC;IACnC,IAAI,CAACW,QAAQ,GAAGD,EAAE;IAClB,OAAO,IAAI;EACb;;EAEAA,EAAE,CAACA,EAAuB,EAAQ;;IAEhC;IACA;IACA;IACApC,MAAM,CAAC,IAAI,CAACsC,MAAM,KAAKZ,SAAS,CAAC;IACjC,IAAI,CAACY,MAAM,GAAGF,EAAE;EAClB;;EAEAG,KAAK,CAACC,CAAS,EAAQ;IACrB,IAAI,CAACb,SAAS,GAAGa,CAAC;IAClB,OAAO,IAAI;EACb;;EAEAC,aAAa,GAAS;IACpBzC,MAAM,CAAC,IAAI,CAACsC,MAAM,KAAKZ,SAAS,CAAC;;IAEjC,IAAI,CAACK,WAAW;IACd,CAAC,IAAI,CAACA,WAAW,GAAG,IAAI,CAACA,WAAW,GAAG,MAAM,GAAG,EAAE,IAAI,wBAAwB;IAChF,IAAI,CAACF,eAAe,GAAG,IAAI;;IAE3B,IAAI,CAACS,MAAM,GAAG,MAAM;MAClB,MAAM,IAAIrD,YAAY,CAAC,oBAAoB,CAAC;IAC9C,CAAC;EACH;;EAEAuC,QAAQ,GAAS;IACf,MAAMkB,cAAc,GAAG,IAAI,CAACd,QAAQ,CAACe,IAAI,CAAC/C,cAAc,CAAC;IACzDI,MAAM,CAAC,IAAI,CAACsC,MAAM,KAAKZ,SAAS,EAAE,MAAM;MACtC,IAAIkB,CAAC,GAAI,0BAAyBF,cAAe,EAAC;MAClD,IAAI,IAAI,CAACzB,iBAAiB,CAAC4B,KAAK,EAAE;QAChCD,CAAC,IAAK,0BAAyB,IAAI,CAAC3B,iBAAiB,CAAC4B,KAAM,EAAC;MAC/D;MACA,OAAOD,CAAC;IACV,CAAC,CAAC;;IAEF,IAAI,IAAI,CAACnB,SAAS,KAAKC,SAAS,EAAE;MAChC;IACF;;IAEA,MAAMpB,IAAI,GAAG,IAAIC,GAAG,EAAU;IAC9B,KAAK,MAAM,CAACuC,UAAU,EAAEC,QAAQ,CAAC,IAAI5D,+BAA+B,CAAC,IAAI,CAACsC,SAAS,CAAC,EAAE;MACpF,KAAK,MAAMuB,aAAa,IAAID,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5C,MAAME,MAAM,GAAGzD,WAAW,CAACsD,UAAU,EAAEE,aAAa,CAAC;QACrDhD,MAAM,CAAC,IAAI,CAAC2B,SAAS,KAAK,CAAC,IAAI,EAAE,SAAS,IAAIsB,MAAM,CAAC,CAAC;;QAEtD;QACA,MAAMC,cAAc,GAAGrD,qBAAqB,CAACoD,MAAM,CAAC;;QAEpD;QACA,MAAME,oBAAoB,GAAGrD,6BAA6B,CAACmD,MAAM,CAAC;QAClEjD,MAAM;QACJ,CAACM,IAAI,CAACQ,GAAG,CAACqC,oBAAoB,CAAC;QAC9B,8CAA6CT,cAAe,KAAIQ,cAAe,EAAC,CAClF;;QACD5C,IAAI,CAACS,GAAG,CAACoC,oBAAoB,CAAC;MAChC;IACF;EACF;;EAEAF,MAAM;EACJG,KAA+F;EAC5E;IACnBpD,MAAM,CAAC,IAAI,CAACyB,SAAS,KAAKC,SAAS,EAAE,oCAAoC,CAAC;IAC1E,IAAI0B,KAAK,YAAYC,QAAQ,EAAE;MAC7B,IAAI,CAAC5B,SAAS,GAAG2B,KAAK,CAAChE,sBAAsB,CAAC;IAChD,CAAC,MAAM;MACL,IAAI,CAACqC,SAAS,GAAG2B,KAAK;IACxB;IACA,OAAO,IAAI;EACb;;EAEAE,YAAY,CAACF,KAAmB,EAAqB;IACnDpD,MAAM,CAAC,IAAI,CAACyB,SAAS,KAAKC,SAAS,EAAE,oCAAoC,CAAC;IAC1E,IAAI,CAACD,SAAS,GAAGrC,sBAAsB,CAACmE,iBAAiB,CAACH,KAAK,CAAC;IAChE,OAAO,IAAI;EACb;;EAEAI,kBAAkB;EAChBT,QAA+F;EAC5E;IACnB,IAAIA,QAAQ,YAAYM,QAAQ,EAAE;MAChC,OAAO,IAAI,CAACJ,MAAM,CAACF,QAAQ,CAAC3D,sBAAsB,CAACqE,aAAa,EAAE,CAAC,CAAC;IACtE,CAAC,MAAM;MACL,OAAO,IAAI,CAACR,MAAM,CAAC7D,sBAAsB,CAACqE,aAAa,EAAE,CAACF,iBAAiB,CAACR,QAAQ,CAAC,CAAC;IACxF;EACF;;EAEA,CAACrC,OAAO,GAA8B;IACpCV,MAAM,CAAC,IAAI,CAACsC,MAAM,KAAKZ,SAAS,EAAE,mCAAmC,CAAC;IACtE,IAAI,CAACD,SAAS,KAAKrC,sBAAsB;IACzC,KAAK,MAAM,CAAC0D,UAAU,EAAEC,QAAQ,CAAC,IAAI5D,+BAA+B,CAAC,IAAI,CAACsC,SAAS,CAAC,EAAE;MACpF,IAAI,IAAI,CAACE,SAAS,KAAK,CAAC,IAAIoB,QAAQ,KAAKrB,SAAS,EAAE;QAClD,MAAM,IAAIgC,eAAe;QACvB,IAAI,CAAC9B,QAAQ;QACbkB,UAAU;QACV,IAAI,CAACjB,eAAe;QACpBkB,QAAQ;QACR,IAAI,CAAC5C,OAAO;QACZ,IAAI,CAACmC,MAAM;QACX,IAAI,CAACD,QAAQ;QACb,IAAI,CAACpB,iBAAiB,CACvB;;MACH,CAAC,MAAM;QACL,MAAM0C,YAAY,GAAGC,KAAK,CAACC,IAAI,CAACd,QAAQ,CAAC;QACzC,IAAIY,YAAY,CAACG,MAAM,IAAI,IAAI,CAACnC,SAAS,EAAE;UACzC,MAAM,IAAI+B,eAAe;UACvB,IAAI,CAAC9B,QAAQ;UACbkB,UAAU;UACV,IAAI,CAACjB,eAAe;UACpB8B,YAAY;UACZ,IAAI,CAACxD,OAAO;UACZ,IAAI,CAACmC,MAAM;UACX,IAAI,CAACD,QAAQ;UACb,IAAI,CAACpB,iBAAiB,CACvB;;QACH,CAAC,MAAM;UACL,KAAK,IAAI8C,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,YAAY,CAACG,MAAM,EAAEC,CAAC,GAAGA,CAAC,GAAG,IAAI,CAACpC,SAAS,EAAE;YAC/D,MAAM,IAAI+B,eAAe;YACvB,IAAI,CAAC9B,QAAQ;YACb,EAAE,GAAGkB,UAAU,EAAEkB,OAAO,EAAED,CAAC,GAAG,IAAI,CAACpC,SAAS,CAAC,CAAC;YAC9C,IAAI,CAACE,eAAe;YACpB8B,YAAY,CAACM,KAAK,CAACF,CAAC,EAAEG,IAAI,CAACC,GAAG,CAACR,YAAY,CAACG,MAAM,EAAEC,CAAC,GAAG,IAAI,CAACpC,SAAS,CAAC,CAAC;YACxE,IAAI,CAACxB,OAAO;YACZ,IAAI,CAACmC,MAAM;YACX,IAAI,CAACD,QAAQ;YACb,IAAI,CAACpB,iBAAiB,CACvB;;UACH;QACF;MACF;IACF;EACF;AACF;;AAEA,MAAMyC,eAAe,CAAoB;;;;;;;;;;;EAWvCjD,WAAW;EACTmB,QAAkB;EAClBqB,MAAU;EACVpB,eAAwB;EACxBkB,QAAkC;EAClC5C,OAAqB;EACrBiC,EAAuB;EACvBC,QAAgE;EAChEpB,iBAAwB;EACxB;IACA,IAAI,CAACmD,EAAE,GAAG,EAAEpD,IAAI,EAAEY,QAAQ,EAAEqB,MAAM,EAAE1D,mBAAmB,CAAC0D,MAAM,CAAC,CAAC,CAAC;IACjE,IAAI,CAACpB,eAAe,GAAGA,eAAe;IACtC,IAAI,CAACoB,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACF,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAAC5C,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACiC,EAAE,GAAGA,EAAE;IACZ,IAAI,CAACC,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAACpB,iBAAiB,GAAGA,iBAAiB;EAC5C;;EAEA,MAAMoD,OAAO;EACXC,GAAqB;EACrBC,WAA8B;EAC9BtB,MAAkB;EAClBuB,SAAkB;EAClBC,cAA2B;EACZ;IACf,IAAI;MACFH,GAAG,CAACI,YAAY,EAAE;MAClB,IAAID,cAAc,KAAK,MAAM,EAAE;QAC7B,MAAM,IAAIxF,YAAY,CAAC,yBAAyB,CAAC;MACnD;;MAEA,MAAM0F,IAAI,GAAG,IAAI,IAAI,CAACxE,OAAO,CAACoE,WAAW,EAAED,GAAG,EAAErB,MAAM,CAAC;MACvD,IAAI;QACF,MAAM0B,IAAI,CAACC,IAAI,EAAE;QACjB,MAAM,IAAI,CAACxC,EAAE,CAACuC,IAAI,CAA6B;MACjD,CAAC,SAAS;QACR;QACA,MAAMA,IAAI,CAACE,QAAQ,EAAE;MACvB;IACF,CAAC,CAAC,OAAOC,EAAE,EAAE;MACX;MACA;MACA;MACA;MACA,IAAIN,SAAS,IAAIM,EAAE,YAAY7F,YAAY,EAAE;QAC3C,MAAM6F,EAAE;MACV;MACAR,GAAG,CAACS,KAAK,CAACD,EAAE,CAAC;IACf,CAAC,SAAS;MACR,IAAI;QACFR,GAAG,CAACU,UAAU,CAACP,cAAc,CAAC;MAChC,CAAC,CAAC,OAAOK,EAAE,EAAE;QACX9E,MAAM,CAAC8E,EAAE,YAAY5F,mBAAmB,CAAC;QACzC4F,EAAE,CAACG,OAAO,GAAI,+BAA8B;QAC5CH,EAAE,CAACjC,KAAK,GAAG,IAAI,CAAC5B,iBAAiB,CAAC4B,KAAK;QACvCyB,GAAG,CAACY,IAAI,CAACJ,EAAE,CAAC;MACd;IACF;EACF;;EAEA,MAAMK,GAAG;EACPb,GAAqB;EACrBc,SAA8B;EAC9BC,YAAwC;EACzB;IACf,MAAMC,iBAAiB,GAAG,CAACC,sBAA2C,KAAK;MACzE,IAAIC,UAAU,GAAG,KAAK;MACtB,KAAK,MAAMC,GAAG,IAAIJ,YAAY,EAAE;QAC9B,MAAMK,QAAQ,GAAGjG,cAAc,CAACgG,GAAG,CAACE,KAAK,EAAEJ,sBAAsB,CAAC;QAClE,IAAIG,QAAQ,KAAKhG,QAAQ,CAACkG,SAAS,IAAIF,QAAQ,KAAKhG,QAAQ,CAACmG,YAAY,EAAE;UACzE;QACF;;QAEA,QAAQJ,GAAG,CAACK,WAAW;UACrB;UACA;UACA,KAAK,MAAM;YACT,OAAO,MAAM;UACf,KAAK,MAAM;YACT;YACAN,UAAU,GAAG,IAAI;YACjB;UACF;YACEvF,WAAW,EAAE,CAAC;;MAEpB;MACA,OAAOuF,UAAU,GAAG,MAAM,GAAG,MAAM;IACrC,CAAC;;IAED,MAAM,EAAEO,qBAAqB,EAAEC,mBAAmB,CAAC,CAAC,GAAG3G,gBAAgB;IACvE,IAAI;MACFiF,GAAG,CAAC2B,KAAK,EAAE;MACX,MAAM1B,WAAW,GAAG,IAAI,CAACpE,OAAO,CAAC+F,eAAe,CAAC,IAAI,CAACjD,MAAM,CAAC;MAC7D,IAAI;QACF,MAAMsB,WAAW,CAACK,IAAI,EAAE;QACxB,IAAI,IAAI,CAACvC,QAAQ,EAAE;UACjB,MAAM,IAAI,CAACA,QAAQ,CAACkC,WAAW,CAAC;QAClC;QACA,MAAMA,WAAW,CAAC4B,QAAQ,EAAE;QAC5BJ,qBAAqB,EAAE;;QAEvB,IAAIK,mCAAkD,GAAGC,OAAO,CAACC,OAAO,EAAE;QAC1E,IAAI,IAAI,CAACvD,QAAQ,EAAE;UACjB,IAAIwD,UAAU,GAAG,CAAC;UAClB,IAAIC,SAAS,GAAG,CAAC;;UAEjB;UACA;UACA,IAAIC,gBAAgB,GAAG,CAAC;UACxB,IAAIC,6BAAuD,GAAGhF,SAAS;UACvE,MAAMiF,uBAAuB,GAAG,MAAM;YACpCF,gBAAgB,IAAI,CAAC;YACrB;YACA;YACA,IAAIC,6BAA6B,EAAE;cACjCA,6BAA6B,EAAE;cAC/BA,6BAA6B,GAAGhF,SAAS;YAC3C;UACF,CAAC;;UAED,KAAK,MAAMkF,SAAS,IAAI,IAAI,CAAC7D,QAAQ,EAAE;YACrC;YACA;YACA;YACA,MAAM8D,aAAa,GAAG,WAAW,GAAGhH,qBAAqB,CAAC+G,SAAS,CAAC;YACpE,MAAME,MAAM,GAAG,IAAIC,KAAK,CAACzC,GAAG,EAAE;cAC5B0C,GAAG,EAAE,CAACC,MAAM,EAAEC,CAAyB,KAAK;gBAC1C,MAAMC,IAAI,GAAG7H,gBAAgB,CAAC8H,SAAS,CAACF,CAAC,CAAC;gBAC1C,IAAI,OAAOC,IAAI,KAAK,UAAU,EAAE;kBAC9BpB,qBAAqB,EAAE;kBACvB,OAAO,UAAU,GAAGsB,IAA6B,EAAE;oBACjD,KAAKjB,mCAAmC,CAACkB,IAAI,CAAC,MAAM;sBAClD;sBACA,KAAK,MAAMC,GAAG,IAAIF,IAAI,EAAE;wBACtB,IAAIE,GAAG,YAAYrG,KAAK,EAAE;0BACxB,IAAI;4BACFqG,GAAG,CAACtC,OAAO,GAAG4B,aAAa,GAAG,IAAI,GAAGU,GAAG,CAACtC,OAAO;0BAClD,CAAC,CAAC,MAAM;4BACN;4BACA,IAAIpC,KAAK,GAAGgE,aAAa;4BACzB,IAAIU,GAAG,CAAC1E,KAAK,EAAEA,KAAK,IAAI,IAAI,GAAG0E,GAAG,CAAC1E,KAAK;4BACxC,IAAI;8BACF0E,GAAG,CAAC1E,KAAK,GAAGA,KAAK;4BACnB,CAAC,CAAC,MAAM;;8BACN;4BAAA,CAEJ;wBACF;sBACF;;;sBAGA,MAAM2E,EAAE,GAAIL,IAAI,CAASM,KAAK,CAACR,MAAM,EAAEI,IAAI,CAAC;sBAC5C;sBACA;sBACArH,MAAM,CAACwH,EAAE,KAAK9F,SAAS,CAAC;oBAC1B,CAAC,CAAC;kBACJ,CAAC;gBACH;gBACA,OAAOyF,IAAI;cACb;YACF,CAAC,CAAC;;YAEF,MAAMlE,MAAM,GAAGzD,WAAW,CAAC,IAAI,CAACyD,MAAM,EAAE2D,SAAS,CAAC;YAClD,MAAMc,YAAY,GAAG,IAAI/H,mBAAmB;YAC1CyF,SAAS,CAACuC,KAAK;YACfvC,SAAS,CAACwC,aAAa;YACvBxC,SAAS,CAACyC,aAAa;YACvB5E,MAAM,CACP;;;YAED;YACA,IAAIwD,gBAAgB,IAAIT,mBAAmB,EAAE;cAC3C,MAAM,IAAIK,OAAO,CAAO,CAAAC,OAAO,KAAI;gBACjC;gBACAtG,MAAM,CAAC0G,6BAA6B,KAAKhF,SAAS,CAAC;gBACnDgF,6BAA6B,GAAGJ,OAAO;cACzC,CAAC,CAAC;YACJ;;YAEAG,gBAAgB,IAAI,CAAC;YACrB;YACA;YACA,MAAMqB,eAAe,GAAG,IAAI,CAACzD,OAAO;YAClCyC,MAAM;YACNvC,WAAW;YACXtB,MAAM;YACN,eAAgB,IAAI;YACpBqC,iBAAiB,CAACoC,YAAY,CAAC,CAChC;;YACEJ,IAAI,CAAC,MAAM;cACVR,MAAM,CAACiB,IAAI,CAAC,IAAI7G,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC,CAAC;YACD8G,KAAK,CAAC,CAAAlD,EAAE,KAAI;cACX,IAAIA,EAAE,YAAY7F,YAAY,EAAE;gBAC9B;gBACA6F,EAAE,CAACG,OAAO,GAAG,mBAAmB,GAAGH,EAAE,CAACG,OAAO;gBAC7C6B,MAAM,CAACiB,IAAI,CAACjD,EAAE,CAAC;gBACf,EAAE0B,SAAS;cACb,CAAC,MAAM;gBACL;gBACAM,MAAM,CAAC/B,KAAK,CAACD,EAAE,CAAC;cAClB;YACF,CAAC,CAAC;YACDmD,OAAO,CAACtB,uBAAuB,CAAC;;YAEnCP,mCAAmC,GAAGA,mCAAmC,CAACkB,IAAI;YAC5E,MAAMQ,eAAe,CACtB;;YACD,EAAEvB,UAAU;UACd;;UAEA;UACA,MAAMH,mCAAmC;;UAEzC,IAAII,SAAS,KAAKD,UAAU,EAAE;YAC5BjC,GAAG,CAAC4D,OAAO,CAAC,IAAIjJ,YAAY,CAAC,2BAA2B,CAAC,CAAC;UAC5D;QACF,CAAC,MAAM;UACL,MAAM,IAAI,CAACoF,OAAO;UAChBC,GAAG;UACHC,WAAW;UACX,IAAI,CAACtB,MAAM;UACX,eAAgB,KAAK;UACrBqC,iBAAiB,CAACF,SAAS,CAAC,CAC7B;;QACH;MACF,CAAC,SAAS;QACRW,qBAAqB,EAAE;QACvB;QACA,MAAMxB,WAAW,CAACM,QAAQ,EAAE;QAC5BkB,qBAAqB,EAAE;MACzB;IACF,CAAC,CAAC,OAAOjB,EAAE,EAAE;MACX;MACA;MACA;MACA;MACAR,GAAG,CAACS,KAAK,CAACD,EAAE,CAAC;IACf,CAAC,SAAS;MACRR,GAAG,CAAC6D,MAAM,EAAE;IACd;EACF;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js
new file mode 100644
index 0000000000..fc2c8c4189
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js
@@ -0,0 +1,4 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/export {};
+//# sourceMappingURL=test_suite_listing.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map
new file mode 100644
index 0000000000..89ae3a6866
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"test_suite_listing.js","names":[],"sources":["../../../src/common/internal/test_suite_listing.ts"],"sourcesContent":["// A listing of all specs within a single suite. This is the (awaited) type of\n// `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated\n// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).\nexport type TestSuiteListing = TestSuiteListingEntry[];\n\nexport type TestSuiteListingEntry = TestSuiteListingEntrySpec | TestSuiteListingEntryReadme;\n\ninterface TestSuiteListingEntrySpec {\n readonly file: string[];\n}\n\ninterface TestSuiteListingEntryReadme {\n readonly file: string[];\n readonly readme: string;\n}\n"],"mappings":";AAAA;AAAA,G"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js
new file mode 100644
index 0000000000..5245079d5d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js
@@ -0,0 +1,576 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from '../util/util.js';
+
+
+import { compareQueries, Ordering } from './query/compare.js';
+import {
+
+TestQueryMultiCase,
+TestQuerySingleCase,
+TestQueryMultiFile,
+TestQueryMultiTest } from
+'./query/query.js';
+import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.js';
+import { stringifySingleParam } from './query/stringify_params.js';
+import { StacklessError } from './util.js';
+
+// `loadTreeForQuery()` loads a TestTree for a given queryToLoad.
+// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad,
+// and under queryToLoad is a tree containing every case matched by queryToLoad.
+//
+// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree.
+// A node is considered "collapsible" if none of the subqueriesToExpand is a StrictSubset
+// of that node.
+//
+// In WebKit/Blink-style web_tests, an expectation file marks individual cts.https.html "variants
+// as "Failure", "Crash", etc. By passing in the list of expectations as the subqueriesToExpand,
+// we can programmatically subdivide the cts.https.html "variants" list to be able to implement
+// arbitrarily-fine suppressions (instead of having to suppress entire test files, which would
+// lose a lot of coverage).
+//
+// `iterateCollapsedNodes()` produces the list of queries for the variants list.
+//
+// Though somewhat complicated, this system has important benefits:
+// - Avoids having to suppress entire test files, which would cause large test coverage loss.
+// - Minimizes the number of page loads needed for fine-grained suppressions.
+// (In the naive case, we could do one page load per test case - but the test suite would
+// take impossibly long to run.)
+// - Enables developers to put any number of tests in one file as appropriate, without worrying
+// about expectation granularity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+export class TestTree {
+ /**
+ * The `queryToLoad` that this test tree was created for.
+ * Test trees are always rooted at `suite:*`, but they only contain nodes that fit
+ * within `forQuery`.
+ *
+ * This is used for `iterateCollapsedNodes` which only starts collapsing at the next
+ * `TestQueryLevel` after `forQuery`.
+ */
+
+
+
+ constructor(forQuery, root) {
+ this.forQuery = forQuery;
+ TestTree.propagateCounts(root);
+ this.root = root;
+ assert(
+ root.query.level === 1 && root.query.depthInLevel === 0,
+ 'TestTree root must be the root (suite:*)');
+
+ }
+
+ /**
+ * Iterate through the leaves of a version of the tree which has been pruned to exclude
+ * subtrees which:
+ * - are at a deeper `TestQueryLevel` than `this.forQuery`, and
+ * - were not a `Ordering.StrictSubset` of any of the `subqueriesToExpand` during tree creation.
+ */
+ iterateCollapsedNodes({
+ includeIntermediateNodes = false,
+ includeEmptySubtrees = false,
+ alwaysExpandThroughLevel
+
+
+
+
+
+
+
+ }) {
+ const expandThroughLevel = Math.max(this.forQuery.level, alwaysExpandThroughLevel);
+ return TestTree.iterateSubtreeNodes(this.root, {
+ includeIntermediateNodes,
+ includeEmptySubtrees,
+ expandThroughLevel
+ });
+ }
+
+ iterateLeaves() {
+ return TestTree.iterateSubtreeLeaves(this.root);
+ }
+
+ /**
+ * Dissolve nodes which have only one child, e.g.:
+ * a,* { a,b,* { a,b:* { ... } } }
+ * collapses down into:
+ * a,* { a,b:* { ... } }
+ * which is less needlessly verbose when displaying the tree in the standalone runner.
+ */
+ dissolveSingleChildTrees() {
+ const newRoot = dissolveSingleChildTrees(this.root);
+ assert(newRoot === this.root);
+ }
+
+ toString() {
+ return TestTree.subtreeToString('(root)', this.root, '');
+ }
+
+ static *iterateSubtreeNodes(
+ subtree,
+ opts)
+
+
+
+
+ {
+ if (opts.includeIntermediateNodes) {
+ yield subtree;
+ }
+
+ for (const [, child] of subtree.children) {
+ if ('children' in child) {
+ // Is a subtree
+ const collapsible = child.collapsible && child.query.level > opts.expandThroughLevel;
+ if (child.children.size > 0 && !collapsible) {
+ yield* TestTree.iterateSubtreeNodes(child, opts);
+ } else if (child.children.size > 0 || opts.includeEmptySubtrees) {
+ // Don't yield empty subtrees (e.g. files with no tests) unless includeEmptySubtrees
+ yield child;
+ }
+ } else {
+ // Is a leaf
+ yield child;
+ }
+ }
+ }
+
+ static *iterateSubtreeLeaves(subtree) {
+ for (const [, child] of subtree.children) {
+ if ('children' in child) {
+ yield* TestTree.iterateSubtreeLeaves(child);
+ } else {
+ yield child;
+ }
+ }
+ }
+
+ /** Propagate the subtreeTODOs/subtreeTests state upward from leaves to parent nodes. */
+ static propagateCounts(subtree) {
+ subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };
+ for (const [, child] of subtree.children) {
+ if ('children' in child) {
+ const counts = TestTree.propagateCounts(child);
+ subtree.subtreeCounts.tests += counts.tests;
+ subtree.subtreeCounts.nodesWithTODO += counts.nodesWithTODO;
+ }
+ }
+ return subtree.subtreeCounts;
+ }
+
+ /** Displays counts in the format `(Nodes with TODOs) / (Total test count)`. */
+ static countsToString(tree) {
+ if (tree.subtreeCounts) {
+ return `${tree.subtreeCounts.nodesWithTODO} / ${tree.subtreeCounts.tests}`;
+ } else {
+ return '';
+ }
+ }
+
+ static subtreeToString(name, tree, indent) {
+ const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-';
+ let s =
+ indent +
+ `${collapsible} ${TestTree.countsToString(tree)} ${JSON.stringify(name)} => ${tree.query}`;
+ if ('children' in tree) {
+ if (tree.description !== undefined) {
+ s += `\n${indent} | ${JSON.stringify(tree.description)}`;
+ }
+
+ for (const [name, child] of tree.children) {
+ s += '\n' + TestTree.subtreeToString(name, child, indent + ' ');
+ }
+ }
+ return s;
+ }
+}
+
+// MAINTENANCE_TODO: Consider having subqueriesToExpand actually impact the depth-order of params
+// in the tree.
+export async function loadTreeForQuery(
+loader,
+queryToLoad,
+subqueriesToExpand)
+{
+ const suite = queryToLoad.suite;
+ const specs = await loader.listing(suite);
+
+ const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries());
+ const seenSubqueriesToExpand = new Array(subqueriesToExpand.length);
+ seenSubqueriesToExpand.fill(false);
+
+ const isCollapsible = (subquery) =>
+ subqueriesToExpandEntries.every(([i, toExpand]) => {
+ const ordering = compareQueries(toExpand, subquery);
+
+ // If toExpand == subquery, no expansion is needed (but it's still "seen").
+ if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true;
+ return ordering !== Ordering.StrictSubset;
+ });
+
+ // L0 = suite-level, e.g. suite:*
+ // L1 = file-level, e.g. suite:a,b:*
+ // L2 = test-level, e.g. suite:a,b:c,d:*
+ // L3 = case-level, e.g. suite:a,b:c,d:
+ let foundCase = false;
+ // L0 is suite:*
+ const subtreeL0 = makeTreeForSuite(suite, isCollapsible);
+ for (const entry of specs) {
+ if (entry.file.length === 0 && 'readme' in entry) {
+ // Suite-level readme.
+ setSubtreeDescriptionAndCountTODOs(subtreeL0, entry.readme);
+ continue;
+ }
+
+ {
+ const queryL1 = new TestQueryMultiFile(suite, entry.file);
+ const orderingL1 = compareQueries(queryL1, queryToLoad);
+ if (orderingL1 === Ordering.Unordered) {
+ // File path is not matched by this query.
+ continue;
+ }
+ }
+
+ if ('readme' in entry) {
+ // Entry is a README that is an ancestor or descendant of the query.
+ // (It's included for display in the standalone runner.)
+
+ // readmeSubtree is suite:a,b,*
+ // (This is always going to dedup with a file path, if there are any test spec files under
+ // the directory that has the README).
+ const readmeSubtree = addSubtreeForDirPath(
+ subtreeL0,
+ entry.file,
+ isCollapsible);
+
+ setSubtreeDescriptionAndCountTODOs(readmeSubtree, entry.readme);
+ continue;
+ }
+ // Entry is a spec file.
+
+ const spec = await loader.importSpecFile(queryToLoad.suite, entry.file);
+ // subtreeL1 is suite:a,b:*
+ const subtreeL1 = addSubtreeForFilePath(
+ subtreeL0,
+ entry.file,
+ isCollapsible);
+
+ setSubtreeDescriptionAndCountTODOs(subtreeL1, spec.description);
+
+ let groupHasTests = false;
+ for (const t of spec.g.iterate()) {
+ groupHasTests = true;
+ {
+ const queryL2 = new TestQueryMultiCase(suite, entry.file, t.testPath, {});
+ const orderingL2 = compareQueries(queryL2, queryToLoad);
+ if (orderingL2 === Ordering.Unordered) {
+ // Test path is not matched by this query.
+ continue;
+ }
+ }
+
+ // subtreeL2 is suite:a,b:c,d:*
+ const subtreeL2 = addSubtreeForTestPath(
+ subtreeL1,
+ t.testPath,
+ t.testCreationStack,
+ isCollapsible);
+
+ // This is 1 test. Set tests=1 then count TODOs.
+ subtreeL2.subtreeCounts ??= { tests: 1, nodesWithTODO: 0 };
+ if (t.description) setSubtreeDescriptionAndCountTODOs(subtreeL2, t.description);
+
+ // MAINTENANCE_TODO: If tree generation gets too slow, avoid actually iterating the cases in a
+ // file if there's no need to (based on the subqueriesToExpand).
+ for (const c of t.iterate()) {
+ {
+ const queryL3 = new TestQuerySingleCase(suite, entry.file, c.id.test, c.id.params);
+ const orderingL3 = compareQueries(queryL3, queryToLoad);
+ if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) {
+ // Case is not matched by this query.
+ continue;
+ }
+ }
+
+ // Leaf for case is suite:a,b:c,d:x=1;y=2
+ addLeafForCase(subtreeL2, c, isCollapsible);
+
+ foundCase = true;
+ }
+ }
+ if (!groupHasTests && !subtreeL1.subtreeCounts) {
+ throw new StacklessError(
+ `${subtreeL1.query} has no tests - it must have "TODO" in its description`);
+
+ }
+ }
+
+ for (const [i, sq] of subqueriesToExpandEntries) {
+ const subquerySeen = seenSubqueriesToExpand[i];
+ if (!subquerySeen) {
+ throw new StacklessError(
+ `subqueriesToExpand entry did not match anything \
+(could be wrong, or could be redundant with a previous subquery):\n ${sq.toString()}`);
+
+ }
+ }
+ assert(foundCase, `Query \`${queryToLoad.toString()}\` does not match any cases`);
+
+ return new TestTree(queryToLoad, subtreeL0);
+}
+
+function setSubtreeDescriptionAndCountTODOs(
+subtree,
+description)
+{
+ assert(subtree.description === undefined);
+ subtree.description = description.trim();
+ subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };
+ if (subtree.description.indexOf('TODO') !== -1) {
+ subtree.subtreeCounts.nodesWithTODO++;
+ }
+}
+
+function makeTreeForSuite(
+suite,
+isCollapsible)
+{
+ const query = new TestQueryMultiFile(suite, []);
+ return {
+ readableRelativeName: suite + kBigSeparator,
+ query,
+ children: new Map(),
+ collapsible: isCollapsible(query)
+ };
+}
+
+function addSubtreeForDirPath(
+tree,
+file,
+isCollapsible)
+{
+ const subqueryFile = [];
+ // To start, tree is suite:*
+ // This loop goes from that -> suite:a,* -> suite:a,b,*
+ for (const part of file) {
+ subqueryFile.push(part);
+ tree = getOrInsertSubtree(part, tree, () => {
+ const query = new TestQueryMultiFile(tree.query.suite, subqueryFile);
+ return {
+ readableRelativeName: part + kPathSeparator + kWildcard,
+ query,
+ collapsible: isCollapsible(query)
+ };
+ });
+ }
+ return tree;
+}
+
+function addSubtreeForFilePath(
+tree,
+file,
+isCollapsible)
+{
+ // To start, tree is suite:*
+ // This goes from that -> suite:a,* -> suite:a,b,*
+ tree = addSubtreeForDirPath(tree, file, isCollapsible);
+ // This goes from that -> suite:a,b:*
+ const subtree = getOrInsertSubtree('', tree, () => {
+ const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []);
+ assert(file.length > 0, 'file path is empty');
+ return {
+ readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard,
+ query,
+ collapsible: isCollapsible(query)
+ };
+ });
+ return subtree;
+}
+
+function addSubtreeForTestPath(
+tree,
+test,
+testCreationStack,
+isCollapsible)
+{
+ const subqueryTest = [];
+ // To start, tree is suite:a,b:*
+ // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,*
+ for (const part of test) {
+ subqueryTest.push(part);
+ tree = getOrInsertSubtree(part, tree, () => {
+ const query = new TestQueryMultiTest(
+ tree.query.suite,
+ tree.query.filePathParts,
+ subqueryTest);
+
+ return {
+ readableRelativeName: part + kPathSeparator + kWildcard,
+ query,
+ collapsible: isCollapsible(query)
+ };
+ });
+ }
+ // This goes from that -> suite:a,b:c,d:*
+ return getOrInsertSubtree('', tree, () => {
+ const query = new TestQueryMultiCase(
+ tree.query.suite,
+ tree.query.filePathParts,
+ subqueryTest,
+ {});
+
+ assert(subqueryTest.length > 0, 'subqueryTest is empty');
+ return {
+ readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard,
+ kWildcard,
+ query,
+ testCreationStack,
+ collapsible: isCollapsible(query)
+ };
+ });
+}
+
+function addLeafForCase(
+tree,
+t,
+checkCollapsible)
+{
+ const query = tree.query;
+ let name = '';
+ const subqueryParams = {};
+
+ // To start, tree is suite:a,b:c,d:*
+ // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;*
+ for (const [k, v] of Object.entries(t.id.params)) {
+ name = stringifySingleParam(k, v);
+ subqueryParams[k] = v;
+
+ tree = getOrInsertSubtree(name, tree, () => {
+ const subquery = new TestQueryMultiCase(
+ query.suite,
+ query.filePathParts,
+ query.testPathParts,
+ subqueryParams);
+
+ return {
+ readableRelativeName: name + kParamSeparator + kWildcard,
+ query: subquery,
+ collapsible: checkCollapsible(subquery)
+ };
+ });
+ }
+
+ // This goes from that -> suite:a,b:c,d:x=1;y=2
+ const subquery = new TestQuerySingleCase(
+ query.suite,
+ query.filePathParts,
+ query.testPathParts,
+ subqueryParams);
+
+ checkCollapsible(subquery); // mark seenSubqueriesToExpand
+ insertLeaf(tree, subquery, t);
+}
+
+function getOrInsertSubtree(
+key,
+parent,
+createSubtree)
+{
+ let v;
+ const child = parent.children.get(key);
+ if (child !== undefined) {
+ assert('children' in child); // Make sure cached subtree is not actually a leaf
+ v = child;
+ } else {
+ v = { ...createSubtree(), children: new Map() };
+ parent.children.set(key, v);
+ }
+ return v;
+}
+
+function insertLeaf(parent, query, t) {
+ const leaf = {
+ readableRelativeName: readableNameForCase(query),
+ query,
+ run: (rec, expectations) => t.run(rec, query, expectations || []),
+ isUnimplemented: t.isUnimplemented
+ };
+
+ // This is a leaf (e.g. s:f:t:x=1;* -> s:f:t:x=1). The key is always ''.
+ const key = '';
+ assert(!parent.children.has(key), `Duplicate testcase: ${query}`);
+ parent.children.set(key, leaf);
+}
+
+function dissolveSingleChildTrees(tree) {
+ if ('children' in tree) {
+ const shouldDissolveThisTree =
+ tree.children.size === 1 && tree.query.depthInLevel !== 0 && tree.description === undefined;
+ if (shouldDissolveThisTree) {
+ // Loops exactly once
+ for (const [, child] of tree.children) {
+ // Recurse on child
+ return dissolveSingleChildTrees(child);
+ }
+ }
+
+ for (const [k, child] of tree.children) {
+ // Recurse on each child
+ const newChild = dissolveSingleChildTrees(child);
+ if (newChild !== child) {
+ tree.children.set(k, newChild);
+ }
+ }
+ }
+ return tree;
+}
+
+/** Generate a readable relative name for a case (used in standalone). */
+function readableNameForCase(query) {
+ const paramsKeys = Object.keys(query.params);
+ if (paramsKeys.length === 0) {
+ return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator;
+ } else {
+ const lastKey = paramsKeys[paramsKeys.length - 1];
+ return stringifySingleParam(lastKey, query.params[lastKey]);
+ }
+}
+//# sourceMappingURL=tree.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map
new file mode 100644
index 0000000000..44a0c7c035
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tree.js","names":["assert","compareQueries","Ordering","TestQueryMultiCase","TestQuerySingleCase","TestQueryMultiFile","TestQueryMultiTest","kBigSeparator","kWildcard","kPathSeparator","kParamSeparator","stringifySingleParam","StacklessError","TestTree","constructor","forQuery","root","propagateCounts","query","level","depthInLevel","iterateCollapsedNodes","includeIntermediateNodes","includeEmptySubtrees","alwaysExpandThroughLevel","expandThroughLevel","Math","max","iterateSubtreeNodes","iterateLeaves","iterateSubtreeLeaves","dissolveSingleChildTrees","newRoot","toString","subtreeToString","subtree","opts","child","children","collapsible","size","subtreeCounts","tests","nodesWithTODO","counts","countsToString","tree","name","indent","s","JSON","stringify","description","undefined","loadTreeForQuery","loader","queryToLoad","subqueriesToExpand","suite","specs","listing","subqueriesToExpandEntries","Array","from","entries","seenSubqueriesToExpand","length","fill","isCollapsible","subquery","every","i","toExpand","ordering","Equal","StrictSubset","foundCase","subtreeL0","makeTreeForSuite","entry","file","setSubtreeDescriptionAndCountTODOs","readme","queryL1","orderingL1","Unordered","readmeSubtree","addSubtreeForDirPath","spec","importSpecFile","subtreeL1","addSubtreeForFilePath","groupHasTests","t","g","iterate","queryL2","testPath","orderingL2","subtreeL2","addSubtreeForTestPath","testCreationStack","c","queryL3","id","test","params","orderingL3","StrictSuperset","addLeafForCase","sq","subquerySeen","trim","indexOf","readableRelativeName","Map","subqueryFile","part","push","getOrInsertSubtree","filePathParts","subqueryTest","checkCollapsible","subqueryParams","k","v","Object","testPathParts","insertLeaf","key","parent","createSubtree","get","set","leaf","readableNameForCase","run","rec","expectations","isUnimplemented","has","shouldDissolveThisTree","newChild","paramsKeys","keys","lastKey"],"sources":["../../../src/common/internal/tree.ts"],"sourcesContent":["import { RunCase, RunFn } from '../internal/test_group.js';\nimport { assert } from '../util/util.js';\n\nimport { TestFileLoader } from './file_loader.js';\nimport { TestParamsRW } from './params_utils.js';\nimport { compareQueries, Ordering } from './query/compare.js';\nimport {\n TestQuery,\n TestQueryMultiCase,\n TestQuerySingleCase,\n TestQueryMultiFile,\n TestQueryMultiTest,\n} from './query/query.js';\nimport { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.js';\nimport { stringifySingleParam } from './query/stringify_params.js';\nimport { StacklessError } from './util.js';\n\n// `loadTreeForQuery()` loads a TestTree for a given queryToLoad.\n// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad,\n// and under queryToLoad is a tree containing every case matched by queryToLoad.\n//\n// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree.\n// A node is considered \"collapsible\" if none of the subqueriesToExpand is a StrictSubset\n// of that node.\n//\n// In WebKit/Blink-style web_tests, an expectation file marks individual cts.https.html \"variants\n// as \"Failure\", \"Crash\", etc. By passing in the list of expectations as the subqueriesToExpand,\n// we can programmatically subdivide the cts.https.html \"variants\" list to be able to implement\n// arbitrarily-fine suppressions (instead of having to suppress entire test files, which would\n// lose a lot of coverage).\n//\n// `iterateCollapsedNodes()` produces the list of queries for the variants list.\n//\n// Though somewhat complicated, this system has important benefits:\n// - Avoids having to suppress entire test files, which would cause large test coverage loss.\n// - Minimizes the number of page loads needed for fine-grained suppressions.\n// (In the naive case, we could do one page load per test case - but the test suite would\n// take impossibly long to run.)\n// - Enables developers to put any number of tests in one file as appropriate, without worrying\n// about expectation granularity.\n\ninterface TestTreeNodeBase<T extends TestQuery> {\n readonly query: T;\n /**\n * Readable \"relative\" name for display in standalone runner.\n * Not always the exact relative name, because sometimes there isn't\n * one (e.g. s:f:* relative to s:f,*), but something that is readable.\n */\n readonly readableRelativeName: string;\n subtreeCounts?: { tests: number; nodesWithTODO: number };\n}\n\nexport interface TestSubtree<T extends TestQuery = TestQuery> extends TestTreeNodeBase<T> {\n readonly children: Map<string, TestTreeNode>;\n readonly collapsible: boolean;\n description?: string;\n readonly testCreationStack?: Error;\n}\n\nexport interface TestTreeLeaf extends TestTreeNodeBase<TestQuerySingleCase> {\n readonly run: RunFn;\n readonly isUnimplemented?: boolean;\n subtreeCounts?: undefined;\n}\n\nexport type TestTreeNode = TestSubtree | TestTreeLeaf;\n\n/**\n * When iterating through \"collapsed\" tree nodes, indicates how many \"query levels\" to traverse\n * through before starting to collapse nodes.\n *\n * Corresponds with TestQueryLevel, but excludes 4 (SingleCase):\n * - 1 = MultiFile. Expands so every file is in the collapsed tree.\n * - 2 = MultiTest. Expands so every test is in the collapsed tree.\n * - 3 = MultiCase. Expands so every case is in the collapsed tree (i.e. collapsing disabled).\n */\nexport type ExpandThroughLevel = 1 | 2 | 3;\n\nexport class TestTree {\n /**\n * The `queryToLoad` that this test tree was created for.\n * Test trees are always rooted at `suite:*`, but they only contain nodes that fit\n * within `forQuery`.\n *\n * This is used for `iterateCollapsedNodes` which only starts collapsing at the next\n * `TestQueryLevel` after `forQuery`.\n */\n readonly forQuery: TestQuery;\n readonly root: TestSubtree;\n\n constructor(forQuery: TestQuery, root: TestSubtree) {\n this.forQuery = forQuery;\n TestTree.propagateCounts(root);\n this.root = root;\n assert(\n root.query.level === 1 && root.query.depthInLevel === 0,\n 'TestTree root must be the root (suite:*)'\n );\n }\n\n /**\n * Iterate through the leaves of a version of the tree which has been pruned to exclude\n * subtrees which:\n * - are at a deeper `TestQueryLevel` than `this.forQuery`, and\n * - were not a `Ordering.StrictSubset` of any of the `subqueriesToExpand` during tree creation.\n */\n iterateCollapsedNodes({\n includeIntermediateNodes = false,\n includeEmptySubtrees = false,\n alwaysExpandThroughLevel,\n }: {\n /** Whether to include intermediate tree nodes or only collapsed-leaves. */\n includeIntermediateNodes?: boolean;\n /** Whether to include collapsed-leaves with no children. */\n includeEmptySubtrees?: boolean;\n /** Never collapse nodes up through this level. */\n alwaysExpandThroughLevel: ExpandThroughLevel;\n }): IterableIterator<Readonly<TestTreeNode>> {\n const expandThroughLevel = Math.max(this.forQuery.level, alwaysExpandThroughLevel);\n return TestTree.iterateSubtreeNodes(this.root, {\n includeIntermediateNodes,\n includeEmptySubtrees,\n expandThroughLevel,\n });\n }\n\n iterateLeaves(): IterableIterator<Readonly<TestTreeLeaf>> {\n return TestTree.iterateSubtreeLeaves(this.root);\n }\n\n /**\n * Dissolve nodes which have only one child, e.g.:\n * a,* { a,b,* { a,b:* { ... } } }\n * collapses down into:\n * a,* { a,b:* { ... } }\n * which is less needlessly verbose when displaying the tree in the standalone runner.\n */\n dissolveSingleChildTrees(): void {\n const newRoot = dissolveSingleChildTrees(this.root);\n assert(newRoot === this.root);\n }\n\n toString(): string {\n return TestTree.subtreeToString('(root)', this.root, '');\n }\n\n static *iterateSubtreeNodes(\n subtree: TestSubtree,\n opts: {\n includeIntermediateNodes: boolean;\n includeEmptySubtrees: boolean;\n expandThroughLevel: number;\n }\n ): IterableIterator<TestTreeNode> {\n if (opts.includeIntermediateNodes) {\n yield subtree;\n }\n\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n // Is a subtree\n const collapsible = child.collapsible && child.query.level > opts.expandThroughLevel;\n if (child.children.size > 0 && !collapsible) {\n yield* TestTree.iterateSubtreeNodes(child, opts);\n } else if (child.children.size > 0 || opts.includeEmptySubtrees) {\n // Don't yield empty subtrees (e.g. files with no tests) unless includeEmptySubtrees\n yield child;\n }\n } else {\n // Is a leaf\n yield child;\n }\n }\n }\n\n static *iterateSubtreeLeaves(subtree: TestSubtree): IterableIterator<TestTreeLeaf> {\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n yield* TestTree.iterateSubtreeLeaves(child);\n } else {\n yield child;\n }\n }\n }\n\n /** Propagate the subtreeTODOs/subtreeTests state upward from leaves to parent nodes. */\n static propagateCounts(subtree: TestSubtree): { tests: number; nodesWithTODO: number } {\n subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n const counts = TestTree.propagateCounts(child);\n subtree.subtreeCounts.tests += counts.tests;\n subtree.subtreeCounts.nodesWithTODO += counts.nodesWithTODO;\n }\n }\n return subtree.subtreeCounts;\n }\n\n /** Displays counts in the format `(Nodes with TODOs) / (Total test count)`. */\n static countsToString(tree: TestTreeNode): string {\n if (tree.subtreeCounts) {\n return `${tree.subtreeCounts.nodesWithTODO} / ${tree.subtreeCounts.tests}`;\n } else {\n return '';\n }\n }\n\n static subtreeToString(name: string, tree: TestTreeNode, indent: string): string {\n const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-';\n let s =\n indent +\n `${collapsible} ${TestTree.countsToString(tree)} ${JSON.stringify(name)} => ${tree.query}`;\n if ('children' in tree) {\n if (tree.description !== undefined) {\n s += `\\n${indent} | ${JSON.stringify(tree.description)}`;\n }\n\n for (const [name, child] of tree.children) {\n s += '\\n' + TestTree.subtreeToString(name, child, indent + ' ');\n }\n }\n return s;\n }\n}\n\n// MAINTENANCE_TODO: Consider having subqueriesToExpand actually impact the depth-order of params\n// in the tree.\nexport async function loadTreeForQuery(\n loader: TestFileLoader,\n queryToLoad: TestQuery,\n subqueriesToExpand: TestQuery[]\n): Promise<TestTree> {\n const suite = queryToLoad.suite;\n const specs = await loader.listing(suite);\n\n const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries());\n const seenSubqueriesToExpand: boolean[] = new Array(subqueriesToExpand.length);\n seenSubqueriesToExpand.fill(false);\n\n const isCollapsible = (subquery: TestQuery) =>\n subqueriesToExpandEntries.every(([i, toExpand]) => {\n const ordering = compareQueries(toExpand, subquery);\n\n // If toExpand == subquery, no expansion is needed (but it's still \"seen\").\n if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true;\n return ordering !== Ordering.StrictSubset;\n });\n\n // L0 = suite-level, e.g. suite:*\n // L1 = file-level, e.g. suite:a,b:*\n // L2 = test-level, e.g. suite:a,b:c,d:*\n // L3 = case-level, e.g. suite:a,b:c,d:\n let foundCase = false;\n // L0 is suite:*\n const subtreeL0 = makeTreeForSuite(suite, isCollapsible);\n for (const entry of specs) {\n if (entry.file.length === 0 && 'readme' in entry) {\n // Suite-level readme.\n setSubtreeDescriptionAndCountTODOs(subtreeL0, entry.readme);\n continue;\n }\n\n {\n const queryL1 = new TestQueryMultiFile(suite, entry.file);\n const orderingL1 = compareQueries(queryL1, queryToLoad);\n if (orderingL1 === Ordering.Unordered) {\n // File path is not matched by this query.\n continue;\n }\n }\n\n if ('readme' in entry) {\n // Entry is a README that is an ancestor or descendant of the query.\n // (It's included for display in the standalone runner.)\n\n // readmeSubtree is suite:a,b,*\n // (This is always going to dedup with a file path, if there are any test spec files under\n // the directory that has the README).\n const readmeSubtree: TestSubtree<TestQueryMultiFile> = addSubtreeForDirPath(\n subtreeL0,\n entry.file,\n isCollapsible\n );\n setSubtreeDescriptionAndCountTODOs(readmeSubtree, entry.readme);\n continue;\n }\n // Entry is a spec file.\n\n const spec = await loader.importSpecFile(queryToLoad.suite, entry.file);\n // subtreeL1 is suite:a,b:*\n const subtreeL1: TestSubtree<TestQueryMultiTest> = addSubtreeForFilePath(\n subtreeL0,\n entry.file,\n isCollapsible\n );\n setSubtreeDescriptionAndCountTODOs(subtreeL1, spec.description);\n\n let groupHasTests = false;\n for (const t of spec.g.iterate()) {\n groupHasTests = true;\n {\n const queryL2 = new TestQueryMultiCase(suite, entry.file, t.testPath, {});\n const orderingL2 = compareQueries(queryL2, queryToLoad);\n if (orderingL2 === Ordering.Unordered) {\n // Test path is not matched by this query.\n continue;\n }\n }\n\n // subtreeL2 is suite:a,b:c,d:*\n const subtreeL2: TestSubtree<TestQueryMultiCase> = addSubtreeForTestPath(\n subtreeL1,\n t.testPath,\n t.testCreationStack,\n isCollapsible\n );\n // This is 1 test. Set tests=1 then count TODOs.\n subtreeL2.subtreeCounts ??= { tests: 1, nodesWithTODO: 0 };\n if (t.description) setSubtreeDescriptionAndCountTODOs(subtreeL2, t.description);\n\n // MAINTENANCE_TODO: If tree generation gets too slow, avoid actually iterating the cases in a\n // file if there's no need to (based on the subqueriesToExpand).\n for (const c of t.iterate()) {\n {\n const queryL3 = new TestQuerySingleCase(suite, entry.file, c.id.test, c.id.params);\n const orderingL3 = compareQueries(queryL3, queryToLoad);\n if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) {\n // Case is not matched by this query.\n continue;\n }\n }\n\n // Leaf for case is suite:a,b:c,d:x=1;y=2\n addLeafForCase(subtreeL2, c, isCollapsible);\n\n foundCase = true;\n }\n }\n if (!groupHasTests && !subtreeL1.subtreeCounts) {\n throw new StacklessError(\n `${subtreeL1.query} has no tests - it must have \"TODO\" in its description`\n );\n }\n }\n\n for (const [i, sq] of subqueriesToExpandEntries) {\n const subquerySeen = seenSubqueriesToExpand[i];\n if (!subquerySeen) {\n throw new StacklessError(\n `subqueriesToExpand entry did not match anything \\\n(could be wrong, or could be redundant with a previous subquery):\\n ${sq.toString()}`\n );\n }\n }\n assert(foundCase, `Query \\`${queryToLoad.toString()}\\` does not match any cases`);\n\n return new TestTree(queryToLoad, subtreeL0);\n}\n\nfunction setSubtreeDescriptionAndCountTODOs(\n subtree: TestSubtree<TestQueryMultiFile>,\n description: string\n) {\n assert(subtree.description === undefined);\n subtree.description = description.trim();\n subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };\n if (subtree.description.indexOf('TODO') !== -1) {\n subtree.subtreeCounts.nodesWithTODO++;\n }\n}\n\nfunction makeTreeForSuite(\n suite: string,\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiFile> {\n const query = new TestQueryMultiFile(suite, []);\n return {\n readableRelativeName: suite + kBigSeparator,\n query,\n children: new Map(),\n collapsible: isCollapsible(query),\n };\n}\n\nfunction addSubtreeForDirPath(\n tree: TestSubtree<TestQueryMultiFile>,\n file: string[],\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiFile> {\n const subqueryFile: string[] = [];\n // To start, tree is suite:*\n // This loop goes from that -> suite:a,* -> suite:a,b,*\n for (const part of file) {\n subqueryFile.push(part);\n tree = getOrInsertSubtree(part, tree, () => {\n const query = new TestQueryMultiFile(tree.query.suite, subqueryFile);\n return {\n readableRelativeName: part + kPathSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n }\n return tree;\n}\n\nfunction addSubtreeForFilePath(\n tree: TestSubtree<TestQueryMultiFile>,\n file: string[],\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiTest> {\n // To start, tree is suite:*\n // This goes from that -> suite:a,* -> suite:a,b,*\n tree = addSubtreeForDirPath(tree, file, isCollapsible);\n // This goes from that -> suite:a,b:*\n const subtree = getOrInsertSubtree('', tree, () => {\n const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []);\n assert(file.length > 0, 'file path is empty');\n return {\n readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n return subtree;\n}\n\nfunction addSubtreeForTestPath(\n tree: TestSubtree<TestQueryMultiTest>,\n test: readonly string[],\n testCreationStack: Error,\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiCase> {\n const subqueryTest: string[] = [];\n // To start, tree is suite:a,b:*\n // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,*\n for (const part of test) {\n subqueryTest.push(part);\n tree = getOrInsertSubtree(part, tree, () => {\n const query = new TestQueryMultiTest(\n tree.query.suite,\n tree.query.filePathParts,\n subqueryTest\n );\n return {\n readableRelativeName: part + kPathSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n }\n // This goes from that -> suite:a,b:c,d:*\n return getOrInsertSubtree('', tree, () => {\n const query = new TestQueryMultiCase(\n tree.query.suite,\n tree.query.filePathParts,\n subqueryTest,\n {}\n );\n assert(subqueryTest.length > 0, 'subqueryTest is empty');\n return {\n readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard,\n kWildcard,\n query,\n testCreationStack,\n collapsible: isCollapsible(query),\n };\n });\n}\n\nfunction addLeafForCase(\n tree: TestSubtree<TestQueryMultiTest>,\n t: RunCase,\n checkCollapsible: (sq: TestQuery) => boolean\n): void {\n const query = tree.query;\n let name: string = '';\n const subqueryParams: TestParamsRW = {};\n\n // To start, tree is suite:a,b:c,d:*\n // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;*\n for (const [k, v] of Object.entries(t.id.params)) {\n name = stringifySingleParam(k, v);\n subqueryParams[k] = v;\n\n tree = getOrInsertSubtree(name, tree, () => {\n const subquery = new TestQueryMultiCase(\n query.suite,\n query.filePathParts,\n query.testPathParts,\n subqueryParams\n );\n return {\n readableRelativeName: name + kParamSeparator + kWildcard,\n query: subquery,\n collapsible: checkCollapsible(subquery),\n };\n });\n }\n\n // This goes from that -> suite:a,b:c,d:x=1;y=2\n const subquery = new TestQuerySingleCase(\n query.suite,\n query.filePathParts,\n query.testPathParts,\n subqueryParams\n );\n checkCollapsible(subquery); // mark seenSubqueriesToExpand\n insertLeaf(tree, subquery, t);\n}\n\nfunction getOrInsertSubtree<T extends TestQuery>(\n key: string,\n parent: TestSubtree,\n createSubtree: () => Omit<TestSubtree<T>, 'children'>\n): TestSubtree<T> {\n let v: TestSubtree<T>;\n const child = parent.children.get(key);\n if (child !== undefined) {\n assert('children' in child); // Make sure cached subtree is not actually a leaf\n v = child as TestSubtree<T>;\n } else {\n v = { ...createSubtree(), children: new Map() };\n parent.children.set(key, v);\n }\n return v;\n}\n\nfunction insertLeaf(parent: TestSubtree, query: TestQuerySingleCase, t: RunCase) {\n const leaf: TestTreeLeaf = {\n readableRelativeName: readableNameForCase(query),\n query,\n run: (rec, expectations) => t.run(rec, query, expectations || []),\n isUnimplemented: t.isUnimplemented,\n };\n\n // This is a leaf (e.g. s:f:t:x=1;* -> s:f:t:x=1). The key is always ''.\n const key = '';\n assert(!parent.children.has(key), `Duplicate testcase: ${query}`);\n parent.children.set(key, leaf);\n}\n\nfunction dissolveSingleChildTrees(tree: TestTreeNode): TestTreeNode {\n if ('children' in tree) {\n const shouldDissolveThisTree =\n tree.children.size === 1 && tree.query.depthInLevel !== 0 && tree.description === undefined;\n if (shouldDissolveThisTree) {\n // Loops exactly once\n for (const [, child] of tree.children) {\n // Recurse on child\n return dissolveSingleChildTrees(child);\n }\n }\n\n for (const [k, child] of tree.children) {\n // Recurse on each child\n const newChild = dissolveSingleChildTrees(child);\n if (newChild !== child) {\n tree.children.set(k, newChild);\n }\n }\n }\n return tree;\n}\n\n/** Generate a readable relative name for a case (used in standalone). */\nfunction readableNameForCase(query: TestQuerySingleCase): string {\n const paramsKeys = Object.keys(query.params);\n if (paramsKeys.length === 0) {\n return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator;\n } else {\n const lastKey = paramsKeys[paramsKeys.length - 1];\n return stringifySingleParam(lastKey, query.params[lastKey]);\n }\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,QAAQ,iBAAiB;;;AAIxC,SAASC,cAAc,EAAEC,QAAQ,QAAQ,oBAAoB;AAC7D;;AAEEC,kBAAkB;AAClBC,mBAAmB;AACnBC,kBAAkB;AAClBC,kBAAkB;AACb,kBAAkB;AACzB,SAASC,aAAa,EAAEC,SAAS,EAAEC,cAAc,EAAEC,eAAe,QAAQ,uBAAuB;AACjG,SAASC,oBAAoB,QAAQ,6BAA6B;AAClE,SAASC,cAAc,QAAQ,WAAW;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,OAAO,MAAMC,QAAQ,CAAC;EACpB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;;;EAIEC,WAAW,CAACC,QAAmB,EAAEC,IAAiB,EAAE;IAClD,IAAI,CAACD,QAAQ,GAAGA,QAAQ;IACxBF,QAAQ,CAACI,eAAe,CAACD,IAAI,CAAC;IAC9B,IAAI,CAACA,IAAI,GAAGA,IAAI;IAChBhB,MAAM;IACJgB,IAAI,CAACE,KAAK,CAACC,KAAK,KAAK,CAAC,IAAIH,IAAI,CAACE,KAAK,CAACE,YAAY,KAAK,CAAC;IACvD,0CAA0C,CAC3C;;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEC,qBAAqB,CAAC;IACpBC,wBAAwB,GAAG,KAAK;IAChCC,oBAAoB,GAAG,KAAK;IAC5BC;;;;;;;;EAQF,CAAC,EAA4C;IAC3C,MAAMC,kBAAkB,GAAGC,IAAI,CAACC,GAAG,CAAC,IAAI,CAACZ,QAAQ,CAACI,KAAK,EAAEK,wBAAwB,CAAC;IAClF,OAAOX,QAAQ,CAACe,mBAAmB,CAAC,IAAI,CAACZ,IAAI,EAAE;MAC7CM,wBAAwB;MACxBC,oBAAoB;MACpBE;IACF,CAAC,CAAC;EACJ;;EAEAI,aAAa,GAA6C;IACxD,OAAOhB,QAAQ,CAACiB,oBAAoB,CAAC,IAAI,CAACd,IAAI,CAAC;EACjD;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEe,wBAAwB,GAAS;IAC/B,MAAMC,OAAO,GAAGD,wBAAwB,CAAC,IAAI,CAACf,IAAI,CAAC;IACnDhB,MAAM,CAACgC,OAAO,KAAK,IAAI,CAAChB,IAAI,CAAC;EAC/B;;EAEAiB,QAAQ,GAAW;IACjB,OAAOpB,QAAQ,CAACqB,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAClB,IAAI,EAAE,EAAE,CAAC;EAC1D;;EAEA,QAAQY,mBAAmB;EACzBO,OAAoB;EACpBC,IAIC;;;;;EAC+B;IAChC,IAAIA,IAAI,CAACd,wBAAwB,EAAE;MACjC,MAAMa,OAAO;IACf;;IAEA,KAAK,MAAM,GAAGE,KAAK,CAAC,IAAIF,OAAO,CAACG,QAAQ,EAAE;MACxC,IAAI,UAAU,IAAID,KAAK,EAAE;QACvB;QACA,MAAME,WAAW,GAAGF,KAAK,CAACE,WAAW,IAAIF,KAAK,CAACnB,KAAK,CAACC,KAAK,GAAGiB,IAAI,CAACX,kBAAkB;QACpF,IAAIY,KAAK,CAACC,QAAQ,CAACE,IAAI,GAAG,CAAC,IAAI,CAACD,WAAW,EAAE;UAC3C,OAAO1B,QAAQ,CAACe,mBAAmB,CAACS,KAAK,EAAED,IAAI,CAAC;QAClD,CAAC,MAAM,IAAIC,KAAK,CAACC,QAAQ,CAACE,IAAI,GAAG,CAAC,IAAIJ,IAAI,CAACb,oBAAoB,EAAE;UAC/D;UACA,MAAMc,KAAK;QACb;MACF,CAAC,MAAM;QACL;QACA,MAAMA,KAAK;MACb;IACF;EACF;;EAEA,QAAQP,oBAAoB,CAACK,OAAoB,EAAkC;IACjF,KAAK,MAAM,GAAGE,KAAK,CAAC,IAAIF,OAAO,CAACG,QAAQ,EAAE;MACxC,IAAI,UAAU,IAAID,KAAK,EAAE;QACvB,OAAOxB,QAAQ,CAACiB,oBAAoB,CAACO,KAAK,CAAC;MAC7C,CAAC,MAAM;QACL,MAAMA,KAAK;MACb;IACF;EACF;;EAEA;EACA,OAAOpB,eAAe,CAACkB,OAAoB,EAA4C;IACrFA,OAAO,CAACM,aAAa,KAAK,EAAEC,KAAK,EAAE,CAAC,EAAEC,aAAa,EAAE,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,GAAGN,KAAK,CAAC,IAAIF,OAAO,CAACG,QAAQ,EAAE;MACxC,IAAI,UAAU,IAAID,KAAK,EAAE;QACvB,MAAMO,MAAM,GAAG/B,QAAQ,CAACI,eAAe,CAACoB,KAAK,CAAC;QAC9CF,OAAO,CAACM,aAAa,CAACC,KAAK,IAAIE,MAAM,CAACF,KAAK;QAC3CP,OAAO,CAACM,aAAa,CAACE,aAAa,IAAIC,MAAM,CAACD,aAAa;MAC7D;IACF;IACA,OAAOR,OAAO,CAACM,aAAa;EAC9B;;EAEA;EACA,OAAOI,cAAc,CAACC,IAAkB,EAAU;IAChD,IAAIA,IAAI,CAACL,aAAa,EAAE;MACtB,OAAQ,GAAEK,IAAI,CAACL,aAAa,CAACE,aAAc,MAAKG,IAAI,CAACL,aAAa,CAACC,KAAM,EAAC;IAC5E,CAAC,MAAM;MACL,OAAO,EAAE;IACX;EACF;;EAEA,OAAOR,eAAe,CAACa,IAAY,EAAED,IAAkB,EAAEE,MAAc,EAAU;IAC/E,MAAMT,WAAW,GAAG,KAAK,IAAIO,IAAI,GAAG,GAAG,GAAGA,IAAI,CAACP,WAAW,GAAG,GAAG,GAAG,GAAG;IACtE,IAAIU,CAAC;IACHD,MAAM;IACL,GAAET,WAAY,IAAG1B,QAAQ,CAACgC,cAAc,CAACC,IAAI,CAAE,IAAGI,IAAI,CAACC,SAAS,CAACJ,IAAI,CAAE,OAAMD,IAAI,CAAC5B,KAAM,EAAC;IAC5F,IAAI,UAAU,IAAI4B,IAAI,EAAE;MACtB,IAAIA,IAAI,CAACM,WAAW,KAAKC,SAAS,EAAE;QAClCJ,CAAC,IAAK,KAAID,MAAO,OAAME,IAAI,CAACC,SAAS,CAACL,IAAI,CAACM,WAAW,CAAE,EAAC;MAC3D;;MAEA,KAAK,MAAM,CAACL,IAAI,EAAEV,KAAK,CAAC,IAAIS,IAAI,CAACR,QAAQ,EAAE;QACzCW,CAAC,IAAI,IAAI,GAAGpC,QAAQ,CAACqB,eAAe,CAACa,IAAI,EAAEV,KAAK,EAAEW,MAAM,GAAG,IAAI,CAAC;MAClE;IACF;IACA,OAAOC,CAAC;EACV;AACF;;AAEA;AACA;AACA,OAAO,eAAeK,gBAAgB;AACpCC,MAAsB;AACtBC,WAAsB;AACtBC,kBAA+B;AACZ;EACnB,MAAMC,KAAK,GAAGF,WAAW,CAACE,KAAK;EAC/B,MAAMC,KAAK,GAAG,MAAMJ,MAAM,CAACK,OAAO,CAACF,KAAK,CAAC;;EAEzC,MAAMG,yBAAyB,GAAGC,KAAK,CAACC,IAAI,CAACN,kBAAkB,CAACO,OAAO,EAAE,CAAC;EAC1E,MAAMC,sBAAiC,GAAG,IAAIH,KAAK,CAACL,kBAAkB,CAACS,MAAM,CAAC;EAC9ED,sBAAsB,CAACE,IAAI,CAAC,KAAK,CAAC;;EAElC,MAAMC,aAAa,GAAG,CAACC,QAAmB;EACxCR,yBAAyB,CAACS,KAAK,CAAC,CAAC,CAACC,CAAC,EAAEC,QAAQ,CAAC,KAAK;IACjD,MAAMC,QAAQ,GAAGxE,cAAc,CAACuE,QAAQ,EAAEH,QAAQ,CAAC;;IAEnD;IACA,IAAII,QAAQ,KAAKvE,QAAQ,CAACwE,KAAK,EAAET,sBAAsB,CAACM,CAAC,CAAC,GAAG,IAAI;IACjE,OAAOE,QAAQ,KAAKvE,QAAQ,CAACyE,YAAY;EAC3C,CAAC,CAAC;;EAEJ;EACA;EACA;EACA;EACA,IAAIC,SAAS,GAAG,KAAK;EACrB;EACA,MAAMC,SAAS,GAAGC,gBAAgB,CAACpB,KAAK,EAAEU,aAAa,CAAC;EACxD,KAAK,MAAMW,KAAK,IAAIpB,KAAK,EAAE;IACzB,IAAIoB,KAAK,CAACC,IAAI,CAACd,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAIa,KAAK,EAAE;MAChD;MACAE,kCAAkC,CAACJ,SAAS,EAAEE,KAAK,CAACG,MAAM,CAAC;MAC3D;IACF;;IAEA;MACE,MAAMC,OAAO,GAAG,IAAI9E,kBAAkB,CAACqD,KAAK,EAAEqB,KAAK,CAACC,IAAI,CAAC;MACzD,MAAMI,UAAU,GAAGnF,cAAc,CAACkF,OAAO,EAAE3B,WAAW,CAAC;MACvD,IAAI4B,UAAU,KAAKlF,QAAQ,CAACmF,SAAS,EAAE;QACrC;QACA;MACF;IACF;;IAEA,IAAI,QAAQ,IAAIN,KAAK,EAAE;MACrB;MACA;;MAEA;MACA;MACA;MACA,MAAMO,aAA8C,GAAGC,oBAAoB;MACzEV,SAAS;MACTE,KAAK,CAACC,IAAI;MACVZ,aAAa,CACd;;MACDa,kCAAkC,CAACK,aAAa,EAAEP,KAAK,CAACG,MAAM,CAAC;MAC/D;IACF;IACA;;IAEA,MAAMM,IAAI,GAAG,MAAMjC,MAAM,CAACkC,cAAc,CAACjC,WAAW,CAACE,KAAK,EAAEqB,KAAK,CAACC,IAAI,CAAC;IACvE;IACA,MAAMU,SAA0C,GAAGC,qBAAqB;IACtEd,SAAS;IACTE,KAAK,CAACC,IAAI;IACVZ,aAAa,CACd;;IACDa,kCAAkC,CAACS,SAAS,EAAEF,IAAI,CAACpC,WAAW,CAAC;;IAE/D,IAAIwC,aAAa,GAAG,KAAK;IACzB,KAAK,MAAMC,CAAC,IAAIL,IAAI,CAACM,CAAC,CAACC,OAAO,EAAE,EAAE;MAChCH,aAAa,GAAG,IAAI;MACpB;QACE,MAAMI,OAAO,GAAG,IAAI7F,kBAAkB,CAACuD,KAAK,EAAEqB,KAAK,CAACC,IAAI,EAAEa,CAAC,CAACI,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzE,MAAMC,UAAU,GAAGjG,cAAc,CAAC+F,OAAO,EAAExC,WAAW,CAAC;QACvD,IAAI0C,UAAU,KAAKhG,QAAQ,CAACmF,SAAS,EAAE;UACrC;UACA;QACF;MACF;;MAEA;MACA,MAAMc,SAA0C,GAAGC,qBAAqB;MACtEV,SAAS;MACTG,CAAC,CAACI,QAAQ;MACVJ,CAAC,CAACQ,iBAAiB;MACnBjC,aAAa,CACd;;MACD;MACA+B,SAAS,CAAC1D,aAAa,KAAK,EAAEC,KAAK,EAAE,CAAC,EAAEC,aAAa,EAAE,CAAC,CAAC,CAAC;MAC1D,IAAIkD,CAAC,CAACzC,WAAW,EAAE6B,kCAAkC,CAACkB,SAAS,EAAEN,CAAC,CAACzC,WAAW,CAAC;;MAE/E;MACA;MACA,KAAK,MAAMkD,CAAC,IAAIT,CAAC,CAACE,OAAO,EAAE,EAAE;QAC3B;UACE,MAAMQ,OAAO,GAAG,IAAInG,mBAAmB,CAACsD,KAAK,EAAEqB,KAAK,CAACC,IAAI,EAAEsB,CAAC,CAACE,EAAE,CAACC,IAAI,EAAEH,CAAC,CAACE,EAAE,CAACE,MAAM,CAAC;UAClF,MAAMC,UAAU,GAAG1G,cAAc,CAACsG,OAAO,EAAE/C,WAAW,CAAC;UACvD,IAAImD,UAAU,KAAKzG,QAAQ,CAACmF,SAAS,IAAIsB,UAAU,KAAKzG,QAAQ,CAAC0G,cAAc,EAAE;YAC/E;YACA;UACF;QACF;;QAEA;QACAC,cAAc,CAACV,SAAS,EAAEG,CAAC,EAAElC,aAAa,CAAC;;QAE3CQ,SAAS,GAAG,IAAI;MAClB;IACF;IACA,IAAI,CAACgB,aAAa,IAAI,CAACF,SAAS,CAACjD,aAAa,EAAE;MAC9C,MAAM,IAAI7B,cAAc;MACrB,GAAE8E,SAAS,CAACxE,KAAM,wDAAuD,CAC3E;;IACH;EACF;;EAEA,KAAK,MAAM,CAACqD,CAAC,EAAEuC,EAAE,CAAC,IAAIjD,yBAAyB,EAAE;IAC/C,MAAMkD,YAAY,GAAG9C,sBAAsB,CAACM,CAAC,CAAC;IAC9C,IAAI,CAACwC,YAAY,EAAE;MACjB,MAAM,IAAInG,cAAc;MACrB;AACT,uEAAuEkG,EAAE,CAAC7E,QAAQ,EAAG,EAAC,CAC/E;;IACH;EACF;EACAjC,MAAM,CAAC4E,SAAS,EAAG,WAAUpB,WAAW,CAACvB,QAAQ,EAAG,6BAA4B,CAAC;;EAEjF,OAAO,IAAIpB,QAAQ,CAAC2C,WAAW,EAAEqB,SAAS,CAAC;AAC7C;;AAEA,SAASI,kCAAkC;AACzC9C,OAAwC;AACxCiB,WAAmB;AACnB;EACApD,MAAM,CAACmC,OAAO,CAACiB,WAAW,KAAKC,SAAS,CAAC;EACzClB,OAAO,CAACiB,WAAW,GAAGA,WAAW,CAAC4D,IAAI,EAAE;EACxC7E,OAAO,CAACM,aAAa,KAAK,EAAEC,KAAK,EAAE,CAAC,EAAEC,aAAa,EAAE,CAAC,CAAC,CAAC;EACxD,IAAIR,OAAO,CAACiB,WAAW,CAAC6D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;IAC9C9E,OAAO,CAACM,aAAa,CAACE,aAAa,EAAE;EACvC;AACF;;AAEA,SAASmC,gBAAgB;AACvBpB,KAAa;AACbU,aAAyC;AACR;EACjC,MAAMlD,KAAK,GAAG,IAAIb,kBAAkB,CAACqD,KAAK,EAAE,EAAE,CAAC;EAC/C,OAAO;IACLwD,oBAAoB,EAAExD,KAAK,GAAGnD,aAAa;IAC3CW,KAAK;IACLoB,QAAQ,EAAE,IAAI6E,GAAG,EAAE;IACnB5E,WAAW,EAAE6B,aAAa,CAAClD,KAAK;EAClC,CAAC;AACH;;AAEA,SAASqE,oBAAoB;AAC3BzC,IAAqC;AACrCkC,IAAc;AACdZ,aAAyC;AACR;EACjC,MAAMgD,YAAsB,GAAG,EAAE;EACjC;EACA;EACA,KAAK,MAAMC,IAAI,IAAIrC,IAAI,EAAE;IACvBoC,YAAY,CAACE,IAAI,CAACD,IAAI,CAAC;IACvBvE,IAAI,GAAGyE,kBAAkB,CAACF,IAAI,EAAEvE,IAAI,EAAE,MAAM;MAC1C,MAAM5B,KAAK,GAAG,IAAIb,kBAAkB,CAACyC,IAAI,CAAC5B,KAAK,CAACwC,KAAK,EAAE0D,YAAY,CAAC;MACpE,OAAO;QACLF,oBAAoB,EAAEG,IAAI,GAAG5G,cAAc,GAAGD,SAAS;QACvDU,KAAK;QACLqB,WAAW,EAAE6B,aAAa,CAAClD,KAAK;MAClC,CAAC;IACH,CAAC,CAAC;EACJ;EACA,OAAO4B,IAAI;AACb;;AAEA,SAAS6C,qBAAqB;AAC5B7C,IAAqC;AACrCkC,IAAc;AACdZ,aAAyC;AACR;EACjC;EACA;EACAtB,IAAI,GAAGyC,oBAAoB,CAACzC,IAAI,EAAEkC,IAAI,EAAEZ,aAAa,CAAC;EACtD;EACA,MAAMjC,OAAO,GAAGoF,kBAAkB,CAAC,EAAE,EAAEzE,IAAI,EAAE,MAAM;IACjD,MAAM5B,KAAK,GAAG,IAAIZ,kBAAkB,CAACwC,IAAI,CAAC5B,KAAK,CAACwC,KAAK,EAAEZ,IAAI,CAAC5B,KAAK,CAACsG,aAAa,EAAE,EAAE,CAAC;IACpFxH,MAAM,CAACgF,IAAI,CAACd,MAAM,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAC7C,OAAO;MACLgD,oBAAoB,EAAElC,IAAI,CAACA,IAAI,CAACd,MAAM,GAAG,CAAC,CAAC,GAAG3D,aAAa,GAAGC,SAAS;MACvEU,KAAK;MACLqB,WAAW,EAAE6B,aAAa,CAAClD,KAAK;IAClC,CAAC;EACH,CAAC,CAAC;EACF,OAAOiB,OAAO;AAChB;;AAEA,SAASiE,qBAAqB;AAC5BtD,IAAqC;AACrC2D,IAAuB;AACvBJ,iBAAwB;AACxBjC,aAAyC;AACR;EACjC,MAAMqD,YAAsB,GAAG,EAAE;EACjC;EACA;EACA,KAAK,MAAMJ,IAAI,IAAIZ,IAAI,EAAE;IACvBgB,YAAY,CAACH,IAAI,CAACD,IAAI,CAAC;IACvBvE,IAAI,GAAGyE,kBAAkB,CAACF,IAAI,EAAEvE,IAAI,EAAE,MAAM;MAC1C,MAAM5B,KAAK,GAAG,IAAIZ,kBAAkB;MAClCwC,IAAI,CAAC5B,KAAK,CAACwC,KAAK;MAChBZ,IAAI,CAAC5B,KAAK,CAACsG,aAAa;MACxBC,YAAY,CACb;;MACD,OAAO;QACLP,oBAAoB,EAAEG,IAAI,GAAG5G,cAAc,GAAGD,SAAS;QACvDU,KAAK;QACLqB,WAAW,EAAE6B,aAAa,CAAClD,KAAK;MAClC,CAAC;IACH,CAAC,CAAC;EACJ;EACA;EACA,OAAOqG,kBAAkB,CAAC,EAAE,EAAEzE,IAAI,EAAE,MAAM;IACxC,MAAM5B,KAAK,GAAG,IAAIf,kBAAkB;IAClC2C,IAAI,CAAC5B,KAAK,CAACwC,KAAK;IAChBZ,IAAI,CAAC5B,KAAK,CAACsG,aAAa;IACxBC,YAAY;IACZ,CAAC,CAAC,CACH;;IACDzH,MAAM,CAACyH,YAAY,CAACvD,MAAM,GAAG,CAAC,EAAE,uBAAuB,CAAC;IACxD,OAAO;MACLgD,oBAAoB,EAAEO,YAAY,CAACA,YAAY,CAACvD,MAAM,GAAG,CAAC,CAAC,GAAG3D,aAAa,GAAGC,SAAS;MACvFA,SAAS;MACTU,KAAK;MACLmF,iBAAiB;MACjB9D,WAAW,EAAE6B,aAAa,CAAClD,KAAK;IAClC,CAAC;EACH,CAAC,CAAC;AACJ;;AAEA,SAAS2F,cAAc;AACrB/D,IAAqC;AACrC+C,CAAU;AACV6B,gBAA4C;AACtC;EACN,MAAMxG,KAAK,GAAG4B,IAAI,CAAC5B,KAAK;EACxB,IAAI6B,IAAY,GAAG,EAAE;EACrB,MAAM4E,cAA4B,GAAG,CAAC,CAAC;;EAEvC;EACA;EACA,KAAK,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC,IAAIC,MAAM,CAAC9D,OAAO,CAAC6B,CAAC,CAACW,EAAE,CAACE,MAAM,CAAC,EAAE;IAChD3D,IAAI,GAAGpC,oBAAoB,CAACiH,CAAC,EAAEC,CAAC,CAAC;IACjCF,cAAc,CAACC,CAAC,CAAC,GAAGC,CAAC;;IAErB/E,IAAI,GAAGyE,kBAAkB,CAACxE,IAAI,EAAED,IAAI,EAAE,MAAM;MAC1C,MAAMuB,QAAQ,GAAG,IAAIlE,kBAAkB;MACrCe,KAAK,CAACwC,KAAK;MACXxC,KAAK,CAACsG,aAAa;MACnBtG,KAAK,CAAC6G,aAAa;MACnBJ,cAAc,CACf;;MACD,OAAO;QACLT,oBAAoB,EAAEnE,IAAI,GAAGrC,eAAe,GAAGF,SAAS;QACxDU,KAAK,EAAEmD,QAAQ;QACf9B,WAAW,EAAEmF,gBAAgB,CAACrD,QAAQ;MACxC,CAAC;IACH,CAAC,CAAC;EACJ;;EAEA;EACA,MAAMA,QAAQ,GAAG,IAAIjE,mBAAmB;EACtCc,KAAK,CAACwC,KAAK;EACXxC,KAAK,CAACsG,aAAa;EACnBtG,KAAK,CAAC6G,aAAa;EACnBJ,cAAc,CACf;;EACDD,gBAAgB,CAACrD,QAAQ,CAAC,CAAC,CAAC;EAC5B2D,UAAU,CAAClF,IAAI,EAAEuB,QAAQ,EAAEwB,CAAC,CAAC;AAC/B;;AAEA,SAAS0B,kBAAkB;AACzBU,GAAW;AACXC,MAAmB;AACnBC,aAAqD;AACrC;EAChB,IAAIN,CAAiB;EACrB,MAAMxF,KAAK,GAAG6F,MAAM,CAAC5F,QAAQ,CAAC8F,GAAG,CAACH,GAAG,CAAC;EACtC,IAAI5F,KAAK,KAAKgB,SAAS,EAAE;IACvBrD,MAAM,CAAC,UAAU,IAAIqC,KAAK,CAAC,CAAC,CAAC;IAC7BwF,CAAC,GAAGxF,KAAuB;EAC7B,CAAC,MAAM;IACLwF,CAAC,GAAG,EAAE,GAAGM,aAAa,EAAE,EAAE7F,QAAQ,EAAE,IAAI6E,GAAG,EAAE,CAAC,CAAC;IAC/Ce,MAAM,CAAC5F,QAAQ,CAAC+F,GAAG,CAACJ,GAAG,EAAEJ,CAAC,CAAC;EAC7B;EACA,OAAOA,CAAC;AACV;;AAEA,SAASG,UAAU,CAACE,MAAmB,EAAEhH,KAA0B,EAAE2E,CAAU,EAAE;EAC/E,MAAMyC,IAAkB,GAAG;IACzBpB,oBAAoB,EAAEqB,mBAAmB,CAACrH,KAAK,CAAC;IAChDA,KAAK;IACLsH,GAAG,EAAE,CAACC,GAAG,EAAEC,YAAY,KAAK7C,CAAC,CAAC2C,GAAG,CAACC,GAAG,EAAEvH,KAAK,EAAEwH,YAAY,IAAI,EAAE,CAAC;IACjEC,eAAe,EAAE9C,CAAC,CAAC8C;EACrB,CAAC;;EAED;EACA,MAAMV,GAAG,GAAG,EAAE;EACdjI,MAAM,CAAC,CAACkI,MAAM,CAAC5F,QAAQ,CAACsG,GAAG,CAACX,GAAG,CAAC,EAAG,uBAAsB/G,KAAM,EAAC,CAAC;EACjEgH,MAAM,CAAC5F,QAAQ,CAAC+F,GAAG,CAACJ,GAAG,EAAEK,IAAI,CAAC;AAChC;;AAEA,SAASvG,wBAAwB,CAACe,IAAkB,EAAgB;EAClE,IAAI,UAAU,IAAIA,IAAI,EAAE;IACtB,MAAM+F,sBAAsB;IAC1B/F,IAAI,CAACR,QAAQ,CAACE,IAAI,KAAK,CAAC,IAAIM,IAAI,CAAC5B,KAAK,CAACE,YAAY,KAAK,CAAC,IAAI0B,IAAI,CAACM,WAAW,KAAKC,SAAS;IAC7F,IAAIwF,sBAAsB,EAAE;MAC1B;MACA,KAAK,MAAM,GAAGxG,KAAK,CAAC,IAAIS,IAAI,CAACR,QAAQ,EAAE;QACrC;QACA,OAAOP,wBAAwB,CAACM,KAAK,CAAC;MACxC;IACF;;IAEA,KAAK,MAAM,CAACuF,CAAC,EAAEvF,KAAK,CAAC,IAAIS,IAAI,CAACR,QAAQ,EAAE;MACtC;MACA,MAAMwG,QAAQ,GAAG/G,wBAAwB,CAACM,KAAK,CAAC;MAChD,IAAIyG,QAAQ,KAAKzG,KAAK,EAAE;QACtBS,IAAI,CAACR,QAAQ,CAAC+F,GAAG,CAACT,CAAC,EAAEkB,QAAQ,CAAC;MAChC;IACF;EACF;EACA,OAAOhG,IAAI;AACb;;AAEA;AACA,SAASyF,mBAAmB,CAACrH,KAA0B,EAAU;EAC/D,MAAM6H,UAAU,GAAGjB,MAAM,CAACkB,IAAI,CAAC9H,KAAK,CAACwF,MAAM,CAAC;EAC5C,IAAIqC,UAAU,CAAC7E,MAAM,KAAK,CAAC,EAAE;IAC3B,OAAOhD,KAAK,CAAC6G,aAAa,CAAC7G,KAAK,CAAC6G,aAAa,CAAC7D,MAAM,GAAG,CAAC,CAAC,GAAG3D,aAAa;EAC5E,CAAC,MAAM;IACL,MAAM0I,OAAO,GAAGF,UAAU,CAACA,UAAU,CAAC7E,MAAM,GAAG,CAAC,CAAC;IACjD,OAAOvD,oBAAoB,CAACsI,OAAO,EAAE/H,KAAK,CAACwF,MAAM,CAACuC,OAAO,CAAC,CAAC;EAC7D;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js
new file mode 100644
index 0000000000..18935e074b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js
@@ -0,0 +1,11 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /**
+ * Error without a stack, which can be used to fatally exit from `tool/` scripts with a
+ * user-friendly message (and no confusing stack).
+ */export class StacklessError extends Error {constructor(message) {
+ super(message);
+ this.stack = undefined;
+ }
+}
+//# sourceMappingURL=util.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map
new file mode 100644
index 0000000000..e29de27b3d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"util.js","names":["StacklessError","Error","constructor","message","stack","undefined"],"sources":["../../../src/common/internal/util.ts"],"sourcesContent":["/**\n * Error without a stack, which can be used to fatally exit from `tool/` scripts with a\n * user-friendly message (and no confusing stack).\n */\nexport class StacklessError extends Error {\n constructor(message: string) {\n super(message);\n this.stack = undefined;\n }\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA;AACA,GACA,OAAO,MAAMA,cAAc,SAASC,KAAK,CAAC,CACxCC,WAAW,CAACC,OAAe,EAAE;IAC3B,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,KAAK,GAAGC,SAAS;EACxB;AACF"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js
new file mode 100644
index 0000000000..3353fd94d7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js
@@ -0,0 +1,3 @@
+// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
+
+export const version = 'b3ce8f38983dc445e66c35d83f1110ce89fba9ba';
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js
new file mode 100644
index 0000000000..946c0bdc11
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js
@@ -0,0 +1,18 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ let windowURL = undefined;
+function getWindowURL() {
+ if (windowURL === undefined) {
+ windowURL = new URL(window.location.toString());
+ }
+ return windowURL;
+}
+
+export function optionEnabled(opt, searchParams = getWindowURL().searchParams) {
+ const val = searchParams.get(opt);
+ return val !== null && val !== '0';
+}
+
+export function optionString(opt, searchParams = getWindowURL().searchParams) {
+ return searchParams.get(opt) || '';
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js
new file mode 100644
index 0000000000..db7af47dab
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js
@@ -0,0 +1,37 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+function node() {
+ const { existsSync } = require('fs');
+
+ return {
+ type: 'node',
+ existsSync,
+ args: process.argv.slice(2),
+ cwd: () => process.cwd(),
+ exit: code => process.exit(code),
+ };
+}
+
+function deno() {
+ function existsSync(path) {
+ try {
+ Deno.readFileSync(path);
+ return true;
+ } catch (err) {
+ return false;
+ }
+ }
+
+ return {
+ type: 'deno',
+ existsSync,
+ args: Deno.args,
+ cwd: Deno.cwd,
+ exit: Deno.exit,
+ };
+}
+
+const sys = typeof globalThis.process !== 'undefined' ? node() : deno();
+
+export default sys;
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js
new file mode 100644
index 0000000000..73eaff46b2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js
@@ -0,0 +1,32 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { setBaseResourcePath } from '../../framework/resources.js';
+import { DefaultTestFileLoader } from '../../internal/file_loader.js';
+import { Logger } from '../../internal/logging/logger.js';
+import { parseQuery } from '../../internal/query/parseQuery.js';
+
+import { assert } from '../../util/util.js';
+
+// Should be DedicatedWorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom".
+
+const loader = new DefaultTestFileLoader();
+
+setBaseResourcePath('../../../resources');
+
+self.onmessage = async ev => {
+ const query = ev.data.query;
+ const expectations = ev.data.expectations;
+ const debug = ev.data.debug;
+
+ Logger.globalDebugMode = debug;
+ const log = new Logger();
+
+ const testcases = Array.from(await loader.loadCases(parseQuery(query)));
+ assert(testcases.length === 1, 'worker query resulted in != 1 cases');
+
+ const testcase = testcases[0];
+ const [rec, result] = log.record(testcase.query.toString());
+ await testcase.run(rec, expectations);
+
+ self.postMessage({ query, result });
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js
new file mode 100644
index 0000000000..f3f9dc62e1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js
@@ -0,0 +1,37 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { LogMessageWithStack } from '../../internal/logging/log_message.js';
+
+export class TestWorker {
+ resolvers = new Map();
+
+ constructor(debug) {
+ this.debug = debug;
+
+ const selfPath = import.meta.url;
+ const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
+ const workerPath = selfPathDir + '/test_worker-worker.js';
+ this.worker = new Worker(workerPath, { type: 'module' });
+ this.worker.onmessage = ev => {
+ const query = ev.data.query;
+ const result = ev.data.result;
+ if (result.logs) {
+ for (const l of result.logs) {
+ Object.setPrototypeOf(l, LogMessageWithStack.prototype);
+ }
+ }
+ this.resolvers.get(query)(result);
+
+ // MAINTENANCE_TODO(kainino0x): update the Logger with this result (or don't have a logger and
+ // update the entire results JSON somehow at some point).
+ };
+ }
+
+ async run(rec, query, expectations = []) {
+ this.worker.postMessage({ query, expectations, debug: this.debug });
+ const workerResult = await new Promise(resolve => {
+ this.resolvers.set(query, resolve);
+ });
+ rec.injectResult(workerResult);
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js
new file mode 100644
index 0000000000..90294223c0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js
@@ -0,0 +1,73 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // Implements the wpt-embedded test runner (see also: wpt/cts.https.html).
+import { globalTestConfig } from '../framework/test_config.js';
+import { DefaultTestFileLoader } from '../internal/file_loader.js';
+import { prettyPrintLog } from '../internal/logging/log_message.js';
+import { Logger } from '../internal/logging/logger.js';
+import { parseQuery } from '../internal/query/parseQuery.js';
+import { parseExpectationsForTestQuery, relativeQueryString } from '../internal/query/query.js';
+import { assert } from '../util/util.js';
+
+import { optionEnabled } from './helper/options.js';
+import { TestWorker } from './helper/test_worker.js';
+
+// testharness.js API (https://web-platform-tests.org/writing-tests/testharness-api.html)
+
+setup({
+ // It's convenient for us to asynchronously add tests to the page. Prevent done() from being
+ // called implicitly when the page is finished loading.
+ explicit_done: true,
+});
+
+void (async () => {
+ const workerEnabled = optionEnabled('worker');
+ const worker = workerEnabled ? new TestWorker(false) : undefined;
+
+ globalTestConfig.unrollConstEvalLoops = optionEnabled('unroll_const_eval_loops');
+
+ const failOnWarnings =
+ typeof shouldWebGPUCTSFailOnWarnings !== 'undefined' && (await shouldWebGPUCTSFailOnWarnings);
+
+ const loader = new DefaultTestFileLoader();
+ const qs = new URLSearchParams(window.location.search).getAll('q');
+ assert(qs.length === 1, 'currently, there must be exactly one ?q=');
+ const filterQuery = parseQuery(qs[0]);
+ const testcases = await loader.loadCases(filterQuery);
+
+ const expectations =
+ typeof loadWebGPUExpectations !== 'undefined'
+ ? parseExpectationsForTestQuery(
+ await loadWebGPUExpectations,
+ filterQuery,
+ new URL(window.location.href)
+ )
+ : [];
+
+ const log = new Logger();
+
+ for (const testcase of testcases) {
+ const name = testcase.query.toString();
+ // For brevity, display the case name "relative" to the ?q= path.
+ const shortName = relativeQueryString(filterQuery, testcase.query) || '(case)';
+
+ const wpt_fn = async () => {
+ const [rec, res] = log.record(name);
+ if (worker) {
+ await worker.run(rec, name, expectations);
+ } else {
+ await testcase.run(rec, expectations);
+ }
+
+ // Unfortunately, it seems not possible to surface any logs for warn/skip.
+ if (res.status === 'fail' || (res.status === 'warn' && failOnWarnings)) {
+ const logs = (res.logs ?? []).map(prettyPrintLog);
+ assert_unreached('\n' + logs.join('\n') + '\n');
+ }
+ };
+
+ promise_test(wpt_fn, shortName);
+ }
+
+ done();
+})();
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js
new file mode 100644
index 0000000000..0c078a11b9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js
@@ -0,0 +1,59 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { resolveOnTimeout } from './util.js';
+
+
+/**
+ * Attempts to trigger JavaScript garbage collection, either using explicit methods if exposed
+ * (may be available in testing environments with special browser runtime flags set), or using
+ * some weird tricks to incur GC pressure. Adopted from the WebGL CTS.
+ */
+export async function attemptGarbageCollection() {
+
+ const w = globalThis;
+ if (w.GCController) {
+ w.GCController.collect();
+ return;
+ }
+
+ if (w.opera && w.opera.collect) {
+ w.opera.collect();
+ return;
+ }
+
+ try {
+ w.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils).
+ garbageCollect();
+ return;
+ } catch (e) {
+
+ // ignore any failure
+ }
+ if (w.gc) {
+ w.gc();
+ return;
+ }
+
+ if (w.CollectGarbage) {
+ w.CollectGarbage();
+ return;
+ }
+
+ let i;
+ function gcRec(n) {
+ if (n < 1) return;
+
+ let temp = { i: 'ab' + i + i / 100000 };
+
+ temp = temp + 'foo';
+ temp; // dummy use of unused variable
+ gcRec(n - 1);
+ }
+ for (i = 0; i < 1000; i++) {
+ gcRec(10);
+ }
+
+ return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps.
+}
+//# sourceMappingURL=collect_garbage.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map
new file mode 100644
index 0000000000..59020707d6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"collect_garbage.js","names":["resolveOnTimeout","attemptGarbageCollection","w","globalThis","GCController","collect","opera","QueryInterface","Components","interfaces","nsIInterfaceRequestor","getInterface","nsIDOMWindowUtils","garbageCollect","e","gc","CollectGarbage","i","gcRec","n","temp"],"sources":["../../../src/common/util/collect_garbage.ts"],"sourcesContent":["import { resolveOnTimeout } from './util.js';\n\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\ndeclare const Components: any;\n\n/**\n * Attempts to trigger JavaScript garbage collection, either using explicit methods if exposed\n * (may be available in testing environments with special browser runtime flags set), or using\n * some weird tricks to incur GC pressure. Adopted from the WebGL CTS.\n */\nexport async function attemptGarbageCollection(): Promise<void> {\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const w: any = globalThis;\n if (w.GCController) {\n w.GCController.collect();\n return;\n }\n\n if (w.opera && w.opera.collect) {\n w.opera.collect();\n return;\n }\n\n try {\n w.QueryInterface(Components.interfaces.nsIInterfaceRequestor)\n .getInterface(Components.interfaces.nsIDOMWindowUtils)\n .garbageCollect();\n return;\n } catch (e) {\n // ignore any failure\n }\n\n if (w.gc) {\n w.gc();\n return;\n }\n\n if (w.CollectGarbage) {\n w.CollectGarbage();\n return;\n }\n\n let i: number;\n function gcRec(n: number): void {\n if (n < 1) return;\n /* eslint-disable @typescript-eslint/restrict-plus-operands */\n let temp: object | string = { i: 'ab' + i + i / 100000 };\n /* eslint-disable @typescript-eslint/restrict-plus-operands */\n temp = temp + 'foo';\n temp; // dummy use of unused variable\n gcRec(n - 1);\n }\n for (i = 0; i < 1000; i++) {\n gcRec(10);\n }\n\n return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps.\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,gBAAgB,QAAQ,WAAW;;;AAK5C;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,wBAAwB,GAAkB;;EAE9D,MAAMC,CAAM,GAAGC,UAAU;EACzB,IAAID,CAAC,CAACE,YAAY,EAAE;IAClBF,CAAC,CAACE,YAAY,CAACC,OAAO,EAAE;IACxB;EACF;;EAEA,IAAIH,CAAC,CAACI,KAAK,IAAIJ,CAAC,CAACI,KAAK,CAACD,OAAO,EAAE;IAC9BH,CAAC,CAACI,KAAK,CAACD,OAAO,EAAE;IACjB;EACF;;EAEA,IAAI;IACFH,CAAC,CAACK,cAAc,CAACC,UAAU,CAACC,UAAU,CAACC,qBAAqB,CAAC;IAC1DC,YAAY,CAACH,UAAU,CAACC,UAAU,CAACG,iBAAiB,CAAC;IACrDC,cAAc,EAAE;IACnB;EACF,CAAC,CAAC,OAAOC,CAAC,EAAE;;IACV;EAAA;EAGF,IAAIZ,CAAC,CAACa,EAAE,EAAE;IACRb,CAAC,CAACa,EAAE,EAAE;IACN;EACF;;EAEA,IAAIb,CAAC,CAACc,cAAc,EAAE;IACpBd,CAAC,CAACc,cAAc,EAAE;IAClB;EACF;;EAEA,IAAIC,CAAS;EACb,SAASC,KAAK,CAACC,CAAS,EAAQ;IAC9B,IAAIA,CAAC,GAAG,CAAC,EAAE;;IAEX,IAAIC,IAAqB,GAAG,EAAEH,CAAC,EAAE,IAAI,GAAGA,CAAC,GAAGA,CAAC,GAAG,MAAM,CAAC,CAAC;;IAExDG,IAAI,GAAGA,IAAI,GAAG,KAAK;IACnBA,IAAI,CAAC,CAAC;IACNF,KAAK,CAACC,CAAC,GAAG,CAAC,CAAC;EACd;EACA,KAAKF,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,IAAI,EAAEA,CAAC,EAAE,EAAE;IACzBC,KAAK,CAAC,EAAE,CAAC;EACX;;EAEA,OAAOlB,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js
new file mode 100644
index 0000000000..7f8f11eacb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js
@@ -0,0 +1,128 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * The interface used for formatting strings with color metadata.
+ *
+ * Currently Colors will use the 'ansi-colors' module if it can be loaded.
+ * If it cannot be loaded, then the Colors implementation is a straight pass-through.
+ *
+ * Colors may also be a no-op if the current environment does not support colors.
+ */
+export let Colors;
+
+try {
+
+ Colors = require('ansi-colors');
+} catch {
+ const passthrough = (s) => s;
+ passthrough.enabled = false;
+ passthrough.reset = passthrough;
+ passthrough.bold = passthrough;
+ passthrough.dim = passthrough;
+ passthrough.italic = passthrough;
+ passthrough.underline = passthrough;
+ passthrough.inverse = passthrough;
+ passthrough.hidden = passthrough;
+ passthrough.strikethrough = passthrough;
+ passthrough.black = passthrough;
+ passthrough.red = passthrough;
+ passthrough.green = passthrough;
+ passthrough.yellow = passthrough;
+ passthrough.blue = passthrough;
+ passthrough.magenta = passthrough;
+ passthrough.cyan = passthrough;
+ passthrough.white = passthrough;
+ passthrough.gray = passthrough;
+ passthrough.grey = passthrough;
+ passthrough.blackBright = passthrough;
+ passthrough.redBright = passthrough;
+ passthrough.greenBright = passthrough;
+ passthrough.yellowBright = passthrough;
+ passthrough.blueBright = passthrough;
+ passthrough.magentaBright = passthrough;
+ passthrough.cyanBright = passthrough;
+ passthrough.whiteBright = passthrough;
+ passthrough.bgBlack = passthrough;
+ passthrough.bgRed = passthrough;
+ passthrough.bgGreen = passthrough;
+ passthrough.bgYellow = passthrough;
+ passthrough.bgBlue = passthrough;
+ passthrough.bgMagenta = passthrough;
+ passthrough.bgCyan = passthrough;
+ passthrough.bgWhite = passthrough;
+ passthrough.bgBlackBright = passthrough;
+ passthrough.bgRedBright = passthrough;
+ passthrough.bgGreenBright = passthrough;
+ passthrough.bgYellowBright = passthrough;
+ passthrough.bgBlueBright = passthrough;
+ passthrough.bgMagentaBright = passthrough;
+ passthrough.bgCyanBright = passthrough;
+ passthrough.bgWhiteBright = passthrough;
+ Colors = passthrough;
+}
+//# sourceMappingURL=colors.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map
new file mode 100644
index 0000000000..581265e20f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"colors.js","names":["Colors","require","passthrough","s","enabled","reset","bold","dim","italic","underline","inverse","hidden","strikethrough","black","red","green","yellow","blue","magenta","cyan","white","gray","grey","blackBright","redBright","greenBright","yellowBright","blueBright","magentaBright","cyanBright","whiteBright","bgBlack","bgRed","bgGreen","bgYellow","bgBlue","bgMagenta","bgCyan","bgWhite","bgBlackBright","bgRedBright","bgGreenBright","bgYellowBright","bgBlueBright","bgMagentaBright","bgCyanBright","bgWhiteBright"],"sources":["../../../src/common/util/colors.ts"],"sourcesContent":["/**\n * The interface used for formatting strings to contain color metadata.\n *\n * Use the interface properties to construct a style, then use the\n * `(s: string): string` function to format the provided string with the given\n * style.\n */\nexport interface Colors {\n // Are colors enabled?\n enabled: boolean;\n\n // Returns the string formatted to contain the specified color or style.\n (s: string): string;\n\n // modifiers\n reset: Colors;\n bold: Colors;\n dim: Colors;\n italic: Colors;\n underline: Colors;\n inverse: Colors;\n hidden: Colors;\n strikethrough: Colors;\n\n // colors\n black: Colors;\n red: Colors;\n green: Colors;\n yellow: Colors;\n blue: Colors;\n magenta: Colors;\n cyan: Colors;\n white: Colors;\n gray: Colors;\n grey: Colors;\n\n // bright colors\n blackBright: Colors;\n redBright: Colors;\n greenBright: Colors;\n yellowBright: Colors;\n blueBright: Colors;\n magentaBright: Colors;\n cyanBright: Colors;\n whiteBright: Colors;\n\n // background colors\n bgBlack: Colors;\n bgRed: Colors;\n bgGreen: Colors;\n bgYellow: Colors;\n bgBlue: Colors;\n bgMagenta: Colors;\n bgCyan: Colors;\n bgWhite: Colors;\n\n // bright background colors\n bgBlackBright: Colors;\n bgRedBright: Colors;\n bgGreenBright: Colors;\n bgYellowBright: Colors;\n bgBlueBright: Colors;\n bgMagentaBright: Colors;\n bgCyanBright: Colors;\n bgWhiteBright: Colors;\n}\n\n/**\n * The interface used for formatting strings with color metadata.\n *\n * Currently Colors will use the 'ansi-colors' module if it can be loaded.\n * If it cannot be loaded, then the Colors implementation is a straight pass-through.\n *\n * Colors may also be a no-op if the current environment does not support colors.\n */\nexport let Colors: Colors;\n\ntry {\n /* eslint-disable-next-line node/no-unpublished-require */\n Colors = require('ansi-colors') as Colors;\n} catch {\n const passthrough = ((s: string) => s) as Colors;\n passthrough.enabled = false;\n passthrough.reset = passthrough;\n passthrough.bold = passthrough;\n passthrough.dim = passthrough;\n passthrough.italic = passthrough;\n passthrough.underline = passthrough;\n passthrough.inverse = passthrough;\n passthrough.hidden = passthrough;\n passthrough.strikethrough = passthrough;\n passthrough.black = passthrough;\n passthrough.red = passthrough;\n passthrough.green = passthrough;\n passthrough.yellow = passthrough;\n passthrough.blue = passthrough;\n passthrough.magenta = passthrough;\n passthrough.cyan = passthrough;\n passthrough.white = passthrough;\n passthrough.gray = passthrough;\n passthrough.grey = passthrough;\n passthrough.blackBright = passthrough;\n passthrough.redBright = passthrough;\n passthrough.greenBright = passthrough;\n passthrough.yellowBright = passthrough;\n passthrough.blueBright = passthrough;\n passthrough.magentaBright = passthrough;\n passthrough.cyanBright = passthrough;\n passthrough.whiteBright = passthrough;\n passthrough.bgBlack = passthrough;\n passthrough.bgRed = passthrough;\n passthrough.bgGreen = passthrough;\n passthrough.bgYellow = passthrough;\n passthrough.bgBlue = passthrough;\n passthrough.bgMagenta = passthrough;\n passthrough.bgCyan = passthrough;\n passthrough.bgWhite = passthrough;\n passthrough.bgBlackBright = passthrough;\n passthrough.bgRedBright = passthrough;\n passthrough.bgGreenBright = passthrough;\n passthrough.bgYellowBright = passthrough;\n passthrough.bgBlueBright = passthrough;\n passthrough.bgMagentaBright = passthrough;\n passthrough.bgCyanBright = passthrough;\n passthrough.bgWhiteBright = passthrough;\n Colors = passthrough;\n}\n"],"mappings":";AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,IAAIA,MAAc;;AAEzB,IAAI;;EAEFA,MAAM,GAAGC,OAAO,CAAC,aAAa,CAAW;AAC3C,CAAC,CAAC,MAAM;EACN,MAAMC,WAAW,GAAI,CAACC,CAAS,KAAKA,CAAY;EAChDD,WAAW,CAACE,OAAO,GAAG,KAAK;EAC3BF,WAAW,CAACG,KAAK,GAAGH,WAAW;EAC/BA,WAAW,CAACI,IAAI,GAAGJ,WAAW;EAC9BA,WAAW,CAACK,GAAG,GAAGL,WAAW;EAC7BA,WAAW,CAACM,MAAM,GAAGN,WAAW;EAChCA,WAAW,CAACO,SAAS,GAAGP,WAAW;EACnCA,WAAW,CAACQ,OAAO,GAAGR,WAAW;EACjCA,WAAW,CAACS,MAAM,GAAGT,WAAW;EAChCA,WAAW,CAACU,aAAa,GAAGV,WAAW;EACvCA,WAAW,CAACW,KAAK,GAAGX,WAAW;EAC/BA,WAAW,CAACY,GAAG,GAAGZ,WAAW;EAC7BA,WAAW,CAACa,KAAK,GAAGb,WAAW;EAC/BA,WAAW,CAACc,MAAM,GAAGd,WAAW;EAChCA,WAAW,CAACe,IAAI,GAAGf,WAAW;EAC9BA,WAAW,CAACgB,OAAO,GAAGhB,WAAW;EACjCA,WAAW,CAACiB,IAAI,GAAGjB,WAAW;EAC9BA,WAAW,CAACkB,KAAK,GAAGlB,WAAW;EAC/BA,WAAW,CAACmB,IAAI,GAAGnB,WAAW;EAC9BA,WAAW,CAACoB,IAAI,GAAGpB,WAAW;EAC9BA,WAAW,CAACqB,WAAW,GAAGrB,WAAW;EACrCA,WAAW,CAACsB,SAAS,GAAGtB,WAAW;EACnCA,WAAW,CAACuB,WAAW,GAAGvB,WAAW;EACrCA,WAAW,CAACwB,YAAY,GAAGxB,WAAW;EACtCA,WAAW,CAACyB,UAAU,GAAGzB,WAAW;EACpCA,WAAW,CAAC0B,aAAa,GAAG1B,WAAW;EACvCA,WAAW,CAAC2B,UAAU,GAAG3B,WAAW;EACpCA,WAAW,CAAC4B,WAAW,GAAG5B,WAAW;EACrCA,WAAW,CAAC6B,OAAO,GAAG7B,WAAW;EACjCA,WAAW,CAAC8B,KAAK,GAAG9B,WAAW;EAC/BA,WAAW,CAAC+B,OAAO,GAAG/B,WAAW;EACjCA,WAAW,CAACgC,QAAQ,GAAGhC,WAAW;EAClCA,WAAW,CAACiC,MAAM,GAAGjC,WAAW;EAChCA,WAAW,CAACkC,SAAS,GAAGlC,WAAW;EACnCA,WAAW,CAACmC,MAAM,GAAGnC,WAAW;EAChCA,WAAW,CAACoC,OAAO,GAAGpC,WAAW;EACjCA,WAAW,CAACqC,aAAa,GAAGrC,WAAW;EACvCA,WAAW,CAACsC,WAAW,GAAGtC,WAAW;EACrCA,WAAW,CAACuC,aAAa,GAAGvC,WAAW;EACvCA,WAAW,CAACwC,cAAc,GAAGxC,WAAW;EACxCA,WAAW,CAACyC,YAAY,GAAGzC,WAAW;EACtCA,WAAW,CAAC0C,eAAe,GAAG1C,WAAW;EACzCA,WAAW,CAAC2C,YAAY,GAAG3C,WAAW;EACtCA,WAAW,CAAC4C,aAAa,GAAG5C,WAAW;EACvCF,MAAM,GAAGE,WAAW;AACtB"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js
new file mode 100644
index 0000000000..845cebf1fc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js
@@ -0,0 +1,40 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/
+
+export function keysOf(obj) {
+ return Object.keys(obj);
+}
+
+export function numericKeysOf(obj) {
+ return Object.keys(obj).map((n) => Number(n));
+}
+
+/**
+ * Creates an info lookup object from a more nicely-formatted table. See below for examples.
+ *
+ * Note: Using `as const` on the arguments to this function is necessary to infer the correct type.
+ */
+export function makeTable(
+
+
+
+
+members,
+defaults,
+table)
+
+
+{
+ const result = {};
+ for (const [k, v] of Object.entries(table)) {
+ const item = {};
+ for (let i = 0; i < members.length; ++i) {
+ item[members[i]] = v[i] ?? defaults[i];
+ }
+ result[k] = item;
+ }
+
+ return result;
+}
+//# sourceMappingURL=data_tables.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map
new file mode 100644
index 0000000000..512f535412
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"data_tables.js","names":["keysOf","obj","Object","keys","numericKeysOf","map","n","Number","makeTable","members","defaults","table","result","k","v","entries","item","i","length"],"sources":["../../../src/common/util/data_tables.ts"],"sourcesContent":["import { ResolveType, ZipKeysWithValues } from './types.js';\n\nexport type valueof<K> = K[keyof K];\n\nexport function keysOf<T extends string>(obj: { [k in T]: unknown }): readonly T[] {\n return (Object.keys(obj) as unknown[]) as T[];\n}\n\nexport function numericKeysOf<T>(obj: object): readonly T[] {\n return (Object.keys(obj).map(n => Number(n)) as unknown[]) as T[];\n}\n\n/**\n * Creates an info lookup object from a more nicely-formatted table. See below for examples.\n *\n * Note: Using `as const` on the arguments to this function is necessary to infer the correct type.\n */\nexport function makeTable<\n Members extends readonly string[],\n Defaults extends readonly unknown[],\n Table extends { readonly [k: string]: readonly unknown[] }\n>(\n members: Members,\n defaults: Defaults,\n table: Table\n): {\n readonly [k in keyof Table]: ResolveType<ZipKeysWithValues<Members, Table[k], Defaults>>;\n} {\n const result: { [k: string]: { [m: string]: unknown } } = {};\n for (const [k, v] of Object.entries<readonly unknown[]>(table)) {\n const item: { [m: string]: unknown } = {};\n for (let i = 0; i < members.length; ++i) {\n item[members[i]] = v[i] ?? defaults[i];\n }\n result[k] = item;\n }\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n return result as any;\n}\n"],"mappings":";AAAA;AAAA;;AAIA,OAAO,SAASA,MAAM,CAAmBC,GAA0B,EAAgB;EACjF,OAAQC,MAAM,CAACC,IAAI,CAACF,GAAG,CAAC;AAC1B;;AAEA,OAAO,SAASG,aAAa,CAAIH,GAAW,EAAgB;EAC1D,OAAQC,MAAM,CAACC,IAAI,CAACF,GAAG,CAAC,CAACI,GAAG,CAAC,CAAAC,CAAC,KAAIC,MAAM,CAACD,CAAC,CAAC,CAAC;AAC9C;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,SAAS;;;;;AAKvBC,OAAgB;AAChBC,QAAkB;AAClBC,KAAY;;;AAGZ;EACA,MAAMC,MAAiD,GAAG,CAAC,CAAC;EAC5D,KAAK,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC,IAAIZ,MAAM,CAACa,OAAO,CAAqBJ,KAAK,CAAC,EAAE;IAC9D,MAAMK,IAA8B,GAAG,CAAC,CAAC;IACzC,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGR,OAAO,CAACS,MAAM,EAAE,EAAED,CAAC,EAAE;MACvCD,IAAI,CAACP,OAAO,CAACQ,CAAC,CAAC,CAAC,GAAGH,CAAC,CAACG,CAAC,CAAC,IAAIP,QAAQ,CAACO,CAAC,CAAC;IACxC;IACAL,MAAM,CAACC,CAAC,CAAC,GAAGG,IAAI;EAClB;;EAEA,OAAOJ,MAAM;AACf"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js
new file mode 100644
index 0000000000..75330edbd2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js
@@ -0,0 +1,75 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /// <reference types="@webgpu/types" />
+import { assert } from './util.js';
+/**
+ * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).
+ * Throws an exception if not found.
+ */
+function defaultGPUProvider() {
+ assert(
+ typeof navigator !== 'undefined' && navigator.gpu !== undefined,
+ 'No WebGPU implementation found');
+
+ return navigator.gpu;
+}
+
+/**
+ * GPUProvider is a function that creates and returns a new GPU instance.
+ * May throw an exception if a GPU cannot be created.
+ */
+
+
+let gpuProvider = defaultGPUProvider;
+
+/**
+ * Sets the function to create and return a new GPU instance.
+ */
+export function setGPUProvider(provider) {
+ assert(impl === undefined, 'setGPUProvider() should not be after getGPU()');
+ gpuProvider = provider;
+}
+
+let impl = undefined;
+
+let defaultRequestAdapterOptions;
+
+export function setDefaultRequestAdapterOptions(options) {
+ if (impl) {
+ throw new Error('must call setDefaultRequestAdapterOptions before getGPU');
+ }
+ defaultRequestAdapterOptions = { ...options };
+}
+
+/**
+ * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).
+ * Throws an exception if not found.
+ */
+export function getGPU() {
+ if (impl) {
+ return impl;
+ }
+
+ impl = gpuProvider();
+
+ if (defaultRequestAdapterOptions) {
+
+ const oldFn = impl.requestAdapter;
+ impl.requestAdapter = function (
+ options)
+ {
+ const promise = oldFn.call(this, { ...defaultRequestAdapterOptions, ...(options || {}) });
+ void promise.then(async (adapter) => {
+ if (adapter) {
+ const info = await adapter.requestAdapterInfo();
+
+ console.log(info);
+ }
+ });
+ return promise;
+ };
+ }
+
+ return impl;
+}
+//# sourceMappingURL=navigator_gpu.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map
new file mode 100644
index 0000000000..cabc9ffd18
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"navigator_gpu.js","names":["assert","defaultGPUProvider","navigator","gpu","undefined","gpuProvider","setGPUProvider","provider","impl","defaultRequestAdapterOptions","setDefaultRequestAdapterOptions","options","Error","getGPU","oldFn","requestAdapter","promise","call","then","adapter","info","requestAdapterInfo","console","log"],"sources":["../../../src/common/util/navigator_gpu.ts"],"sourcesContent":["/// <reference types=\"@webgpu/types\" />\n\nimport { assert } from './util.js';\n\n/**\n * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).\n * Throws an exception if not found.\n */\nfunction defaultGPUProvider(): GPU {\n assert(\n typeof navigator !== 'undefined' && navigator.gpu !== undefined,\n 'No WebGPU implementation found'\n );\n return navigator.gpu;\n}\n\n/**\n * GPUProvider is a function that creates and returns a new GPU instance.\n * May throw an exception if a GPU cannot be created.\n */\nexport type GPUProvider = () => GPU;\n\nlet gpuProvider: GPUProvider = defaultGPUProvider;\n\n/**\n * Sets the function to create and return a new GPU instance.\n */\nexport function setGPUProvider(provider: GPUProvider) {\n assert(impl === undefined, 'setGPUProvider() should not be after getGPU()');\n gpuProvider = provider;\n}\n\nlet impl: GPU | undefined = undefined;\n\nlet defaultRequestAdapterOptions: GPURequestAdapterOptions | undefined;\n\nexport function setDefaultRequestAdapterOptions(options: GPURequestAdapterOptions) {\n if (impl) {\n throw new Error('must call setDefaultRequestAdapterOptions before getGPU');\n }\n defaultRequestAdapterOptions = { ...options };\n}\n\n/**\n * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).\n * Throws an exception if not found.\n */\nexport function getGPU(): GPU {\n if (impl) {\n return impl;\n }\n\n impl = gpuProvider();\n\n if (defaultRequestAdapterOptions) {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const oldFn = impl.requestAdapter;\n impl.requestAdapter = function (\n options?: GPURequestAdapterOptions\n ): Promise<GPUAdapter | null> {\n const promise = oldFn.call(this, { ...defaultRequestAdapterOptions, ...(options || {}) });\n void promise.then(async adapter => {\n if (adapter) {\n const info = await adapter.requestAdapterInfo();\n // eslint-disable-next-line no-console\n console.log(info);\n }\n });\n return promise;\n };\n }\n\n return impl;\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AAEA,SAASA,MAAM,QAAQ,WAAW;AAElC;AACA;AACA;AACA;AACA,SAASC,kBAAkB,GAAQ;EACjCD,MAAM;EACJ,OAAOE,SAAS,KAAK,WAAW,IAAIA,SAAS,CAACC,GAAG,KAAKC,SAAS;EAC/D,gCAAgC,CACjC;;EACD,OAAOF,SAAS,CAACC,GAAG;AACtB;;AAEA;AACA;AACA;AACA;;;AAGA,IAAIE,WAAwB,GAAGJ,kBAAkB;;AAEjD;AACA;AACA;AACA,OAAO,SAASK,cAAc,CAACC,QAAqB,EAAE;EACpDP,MAAM,CAACQ,IAAI,KAAKJ,SAAS,EAAE,+CAA+C,CAAC;EAC3EC,WAAW,GAAGE,QAAQ;AACxB;;AAEA,IAAIC,IAAqB,GAAGJ,SAAS;;AAErC,IAAIK,4BAAkE;;AAEtE,OAAO,SAASC,+BAA+B,CAACC,OAAiC,EAAE;EACjF,IAAIH,IAAI,EAAE;IACR,MAAM,IAAII,KAAK,CAAC,yDAAyD,CAAC;EAC5E;EACAH,4BAA4B,GAAG,EAAE,GAAGE,OAAO,CAAC,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASE,MAAM,GAAQ;EAC5B,IAAIL,IAAI,EAAE;IACR,OAAOA,IAAI;EACb;;EAEAA,IAAI,GAAGH,WAAW,EAAE;;EAEpB,IAAII,4BAA4B,EAAE;;IAEhC,MAAMK,KAAK,GAAGN,IAAI,CAACO,cAAc;IACjCP,IAAI,CAACO,cAAc,GAAG;IACpBJ,OAAkC;IACN;MAC5B,MAAMK,OAAO,GAAGF,KAAK,CAACG,IAAI,CAAC,IAAI,EAAE,EAAE,GAAGR,4BAA4B,EAAE,IAAIE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;MACzF,KAAKK,OAAO,CAACE,IAAI,CAAC,OAAMC,OAAO,KAAI;QACjC,IAAIA,OAAO,EAAE;UACX,MAAMC,IAAI,GAAG,MAAMD,OAAO,CAACE,kBAAkB,EAAE;;UAE/CC,OAAO,CAACC,GAAG,CAACH,IAAI,CAAC;QACnB;MACF,CAAC,CAAC;MACF,OAAOJ,OAAO;IAChB,CAAC;EACH;;EAEA,OAAOR,IAAI;AACb"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js
new file mode 100644
index 0000000000..23ffe4c45a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js
@@ -0,0 +1,150 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { assert } from './util.js'; // The state of the preprocessor is a stack of States.
+var
+State;
+
+
+// Have already seen a passing condition; now skipping the rest
+
+
+// The transitions in the state space are the following preprocessor directives:
+// - Sibling elif
+// - Sibling else
+// - Sibling endif
+// - Child if
+(function (State) {State[State["Seeking"] = 0] = "Seeking";State[State["Passing"] = 1] = "Passing";State[State["Skipping"] = 2] = "Skipping";})(State || (State = {}));class Directive {
+
+
+ constructor(depth) {
+ this.depth = depth;
+ }
+
+ checkDepth(stack) {
+ assert(
+ stack.length === this.depth,
+ `Number of "$"s must match nesting depth, currently ${stack.length} (e.g. $if $$if $$endif $endif)`);
+
+ }
+
+
+}
+
+class If extends Directive {
+
+
+ constructor(depth, predicate) {
+ super(depth);
+ this.predicate = predicate;
+ }
+
+ applyTo(stack) {
+ this.checkDepth(stack);
+ const parentState = stack[stack.length - 1].state;
+ stack.push({
+ allowsFollowingElse: true,
+ state:
+ parentState !== State.Passing ?
+ State.Skipping :
+ this.predicate ?
+ State.Passing :
+ State.Seeking
+ });
+ }
+}
+
+class ElseIf extends If {
+ applyTo(stack) {
+ assert(stack.length >= 1);
+ const { allowsFollowingElse, state: siblingState } = stack.pop();
+ this.checkDepth(stack);
+ assert(allowsFollowingElse, 'pp.elif after pp.else');
+ if (siblingState !== State.Seeking) {
+ stack.push({ allowsFollowingElse: true, state: State.Skipping });
+ } else {
+ super.applyTo(stack);
+ }
+ }
+}
+
+class Else extends Directive {
+ applyTo(stack) {
+ assert(stack.length >= 1);
+ const { allowsFollowingElse, state: siblingState } = stack.pop();
+ this.checkDepth(stack);
+ assert(allowsFollowingElse, 'pp.else after pp.else');
+ stack.push({
+ allowsFollowingElse: false,
+ state: siblingState === State.Seeking ? State.Passing : State.Skipping
+ });
+ }
+}
+
+class EndIf extends Directive {
+ applyTo(stack) {
+ stack.pop();
+ this.checkDepth(stack);
+ }
+}
+
+/**
+ * A simple template-based, non-line-based preprocessor implementing if/elif/else/endif.
+ *
+ * @example
+ * ```
+ * const shader = pp`
+ * ${pp._if(expr)}
+ * const x: ${type} = ${value};
+ * ${pp._elif(expr)}
+ * ${pp.__if(expr)}
+ * ...
+ * ${pp.__else}
+ * ...
+ * ${pp.__endif}
+ * ${pp._endif}`;
+ * ```
+ *
+ * @param strings - The array of constant string chunks of the template string.
+ * @param ...values - The array of interpolated `${}` values within the template string.
+ */
+export function pp(
+strings,
+...values)
+{
+ let result = '';
+ const stateStack = [{ allowsFollowingElse: false, state: State.Passing }];
+
+ for (let i = 0; i < values.length; ++i) {
+ const passing = stateStack[stateStack.length - 1].state === State.Passing;
+ if (passing) {
+ result += strings[i];
+ }
+
+ const value = values[i];
+ if (value instanceof Directive) {
+ value.applyTo(stateStack);
+ } else {
+ if (passing) {
+ result += value;
+ }
+ }
+ }
+ assert(stateStack.length === 1, 'Unterminated preprocessor condition at end of file');
+ result += strings[values.length];
+
+ return result;
+}
+pp._if = (predicate) => new If(1, predicate);
+pp._elif = (predicate) => new ElseIf(1, predicate);
+pp._else = new Else(1);
+pp._endif = new EndIf(1);
+pp.__if = (predicate) => new If(2, predicate);
+pp.__elif = (predicate) => new ElseIf(2, predicate);
+pp.__else = new Else(2);
+pp.__endif = new EndIf(2);
+pp.___if = (predicate) => new If(3, predicate);
+pp.___elif = (predicate) => new ElseIf(3, predicate);
+pp.___else = new Else(3);
+pp.___endif = new EndIf(3);
+// Add more if needed.
+//# sourceMappingURL=preprocessor.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map
new file mode 100644
index 0000000000..b58f288efe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"preprocessor.js","names":["assert","State","Directive","constructor","depth","checkDepth","stack","length","If","predicate","applyTo","parentState","state","push","allowsFollowingElse","Passing","Skipping","Seeking","ElseIf","siblingState","pop","Else","EndIf","pp","strings","values","result","stateStack","i","passing","value","_if","_elif","_else","_endif","__if","__elif","__else","__endif","___if","___elif","___else","___endif"],"sources":["../../../src/common/util/preprocessor.ts"],"sourcesContent":["import { assert } from './util.js';\n\n// The state of the preprocessor is a stack of States.\ntype StateStack = { allowsFollowingElse: boolean; state: State }[];\nconst enum State {\n Seeking, // Still looking for a passing condition\n Passing, // Currently inside a passing condition (the root is always in this state)\n Skipping, // Have already seen a passing condition; now skipping the rest\n}\n\n// The transitions in the state space are the following preprocessor directives:\n// - Sibling elif\n// - Sibling else\n// - Sibling endif\n// - Child if\nabstract class Directive {\n private readonly depth: number;\n\n constructor(depth: number) {\n this.depth = depth;\n }\n\n protected checkDepth(stack: StateStack): void {\n assert(\n stack.length === this.depth,\n `Number of \"$\"s must match nesting depth, currently ${stack.length} (e.g. $if $$if $$endif $endif)`\n );\n }\n\n abstract applyTo(stack: StateStack): void;\n}\n\nclass If extends Directive {\n private readonly predicate: boolean;\n\n constructor(depth: number, predicate: boolean) {\n super(depth);\n this.predicate = predicate;\n }\n\n applyTo(stack: StateStack) {\n this.checkDepth(stack);\n const parentState = stack[stack.length - 1].state;\n stack.push({\n allowsFollowingElse: true,\n state:\n parentState !== State.Passing\n ? State.Skipping\n : this.predicate\n ? State.Passing\n : State.Seeking,\n });\n }\n}\n\nclass ElseIf extends If {\n applyTo(stack: StateStack) {\n assert(stack.length >= 1);\n const { allowsFollowingElse, state: siblingState } = stack.pop()!;\n this.checkDepth(stack);\n assert(allowsFollowingElse, 'pp.elif after pp.else');\n if (siblingState !== State.Seeking) {\n stack.push({ allowsFollowingElse: true, state: State.Skipping });\n } else {\n super.applyTo(stack);\n }\n }\n}\n\nclass Else extends Directive {\n applyTo(stack: StateStack) {\n assert(stack.length >= 1);\n const { allowsFollowingElse, state: siblingState } = stack.pop()!;\n this.checkDepth(stack);\n assert(allowsFollowingElse, 'pp.else after pp.else');\n stack.push({\n allowsFollowingElse: false,\n state: siblingState === State.Seeking ? State.Passing : State.Skipping,\n });\n }\n}\n\nclass EndIf extends Directive {\n applyTo(stack: StateStack) {\n stack.pop();\n this.checkDepth(stack);\n }\n}\n\n/**\n * A simple template-based, non-line-based preprocessor implementing if/elif/else/endif.\n *\n * @example\n * ```\n * const shader = pp`\n * ${pp._if(expr)}\n * const x: ${type} = ${value};\n * ${pp._elif(expr)}\n * ${pp.__if(expr)}\n * ...\n * ${pp.__else}\n * ...\n * ${pp.__endif}\n * ${pp._endif}`;\n * ```\n *\n * @param strings - The array of constant string chunks of the template string.\n * @param ...values - The array of interpolated `${}` values within the template string.\n */\nexport function pp(\n strings: TemplateStringsArray,\n ...values: ReadonlyArray<Directive | string | number>\n): string {\n let result = '';\n const stateStack: StateStack = [{ allowsFollowingElse: false, state: State.Passing }];\n\n for (let i = 0; i < values.length; ++i) {\n const passing = stateStack[stateStack.length - 1].state === State.Passing;\n if (passing) {\n result += strings[i];\n }\n\n const value = values[i];\n if (value instanceof Directive) {\n value.applyTo(stateStack);\n } else {\n if (passing) {\n result += value;\n }\n }\n }\n assert(stateStack.length === 1, 'Unterminated preprocessor condition at end of file');\n result += strings[values.length];\n\n return result;\n}\npp._if = (predicate: boolean) => new If(1, predicate);\npp._elif = (predicate: boolean) => new ElseIf(1, predicate);\npp._else = new Else(1);\npp._endif = new EndIf(1);\npp.__if = (predicate: boolean) => new If(2, predicate);\npp.__elif = (predicate: boolean) => new ElseIf(2, predicate);\npp.__else = new Else(2);\npp.__endif = new EndIf(2);\npp.___if = (predicate: boolean) => new If(3, predicate);\npp.___elif = (predicate: boolean) => new ElseIf(3, predicate);\npp.___else = new Else(3);\npp.___endif = new EndIf(3);\n// Add more if needed.\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,MAAM,QAAQ,WAAW,CAAC,CAEnC;AAAA;AAEWC,KAAK;;;AAGJ;;;AAGZ;AACA;AACA;AACA;AACA;AAAA,WAVWA,KAAK,GAALA,KAAK,CAALA,KAAK,6BAALA,KAAK,CAALA,KAAK,6BAALA,KAAK,CAALA,KAAK,kCAALA,KAAK,KAALA,KAAK,QAWhB,MAAeC,SAAS,CAAC;;;EAGvBC,WAAW,CAACC,KAAa,EAAE;IACzB,IAAI,CAACA,KAAK,GAAGA,KAAK;EACpB;;EAEUC,UAAU,CAACC,KAAiB,EAAQ;IAC5CN,MAAM;IACJM,KAAK,CAACC,MAAM,KAAK,IAAI,CAACH,KAAK;IAC1B,sDAAqDE,KAAK,CAACC,MAAO,iCAAgC,CACpG;;EACH;;;AAGF;;AAEA,MAAMC,EAAE,SAASN,SAAS,CAAC;;;EAGzBC,WAAW,CAACC,KAAa,EAAEK,SAAkB,EAAE;IAC7C,KAAK,CAACL,KAAK,CAAC;IACZ,IAAI,CAACK,SAAS,GAAGA,SAAS;EAC5B;;EAEAC,OAAO,CAACJ,KAAiB,EAAE;IACzB,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACtB,MAAMK,WAAW,GAAGL,KAAK,CAACA,KAAK,CAACC,MAAM,GAAG,CAAC,CAAC,CAACK,KAAK;IACjDN,KAAK,CAACO,IAAI,CAAC;MACTC,mBAAmB,EAAE,IAAI;MACzBF,KAAK;MACHD,WAAW,KAAKV,KAAK,CAACc,OAAO;MACzBd,KAAK,CAACe,QAAQ;MACd,IAAI,CAACP,SAAS;MACdR,KAAK,CAACc,OAAO;MACbd,KAAK,CAACgB;IACd,CAAC,CAAC;EACJ;AACF;;AAEA,MAAMC,MAAM,SAASV,EAAE,CAAC;EACtBE,OAAO,CAACJ,KAAiB,EAAE;IACzBN,MAAM,CAACM,KAAK,CAACC,MAAM,IAAI,CAAC,CAAC;IACzB,MAAM,EAAEO,mBAAmB,EAAEF,KAAK,EAAEO,YAAY,CAAC,CAAC,GAAGb,KAAK,CAACc,GAAG,EAAG;IACjE,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;IACtBN,MAAM,CAACc,mBAAmB,EAAE,uBAAuB,CAAC;IACpD,IAAIK,YAAY,KAAKlB,KAAK,CAACgB,OAAO,EAAE;MAClCX,KAAK,CAACO,IAAI,CAAC,EAAEC,mBAAmB,EAAE,IAAI,EAAEF,KAAK,EAAEX,KAAK,CAACe,QAAQ,CAAC,CAAC,CAAC;IAClE,CAAC,MAAM;MACL,KAAK,CAACN,OAAO,CAACJ,KAAK,CAAC;IACtB;EACF;AACF;;AAEA,MAAMe,IAAI,SAASnB,SAAS,CAAC;EAC3BQ,OAAO,CAACJ,KAAiB,EAAE;IACzBN,MAAM,CAACM,KAAK,CAACC,MAAM,IAAI,CAAC,CAAC;IACzB,MAAM,EAAEO,mBAAmB,EAAEF,KAAK,EAAEO,YAAY,CAAC,CAAC,GAAGb,KAAK,CAACc,GAAG,EAAG;IACjE,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;IACtBN,MAAM,CAACc,mBAAmB,EAAE,uBAAuB,CAAC;IACpDR,KAAK,CAACO,IAAI,CAAC;MACTC,mBAAmB,EAAE,KAAK;MAC1BF,KAAK,EAAEO,YAAY,KAAKlB,KAAK,CAACgB,OAAO,GAAGhB,KAAK,CAACc,OAAO,GAAGd,KAAK,CAACe;IAChE,CAAC,CAAC;EACJ;AACF;;AAEA,MAAMM,KAAK,SAASpB,SAAS,CAAC;EAC5BQ,OAAO,CAACJ,KAAiB,EAAE;IACzBA,KAAK,CAACc,GAAG,EAAE;IACX,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;EACxB;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASiB,EAAE;AAChBC,OAA6B;AAC7B,GAAGC,MAAkD;AAC7C;EACR,IAAIC,MAAM,GAAG,EAAE;EACf,MAAMC,UAAsB,GAAG,CAAC,EAAEb,mBAAmB,EAAE,KAAK,EAAEF,KAAK,EAAEX,KAAK,CAACc,OAAO,CAAC,CAAC,CAAC;;EAErF,KAAK,IAAIa,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGH,MAAM,CAAClB,MAAM,EAAE,EAAEqB,CAAC,EAAE;IACtC,MAAMC,OAAO,GAAGF,UAAU,CAACA,UAAU,CAACpB,MAAM,GAAG,CAAC,CAAC,CAACK,KAAK,KAAKX,KAAK,CAACc,OAAO;IACzE,IAAIc,OAAO,EAAE;MACXH,MAAM,IAAIF,OAAO,CAACI,CAAC,CAAC;IACtB;;IAEA,MAAME,KAAK,GAAGL,MAAM,CAACG,CAAC,CAAC;IACvB,IAAIE,KAAK,YAAY5B,SAAS,EAAE;MAC9B4B,KAAK,CAACpB,OAAO,CAACiB,UAAU,CAAC;IAC3B,CAAC,MAAM;MACL,IAAIE,OAAO,EAAE;QACXH,MAAM,IAAII,KAAK;MACjB;IACF;EACF;EACA9B,MAAM,CAAC2B,UAAU,CAACpB,MAAM,KAAK,CAAC,EAAE,oDAAoD,CAAC;EACrFmB,MAAM,IAAIF,OAAO,CAACC,MAAM,CAAClB,MAAM,CAAC;;EAEhC,OAAOmB,MAAM;AACf;AACAH,EAAE,CAACQ,GAAG,GAAG,CAACtB,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACrDc,EAAE,CAACS,KAAK,GAAG,CAACvB,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC3Dc,EAAE,CAACU,KAAK,GAAG,IAAIZ,IAAI,CAAC,CAAC,CAAC;AACtBE,EAAE,CAACW,MAAM,GAAG,IAAIZ,KAAK,CAAC,CAAC,CAAC;AACxBC,EAAE,CAACY,IAAI,GAAG,CAAC1B,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACtDc,EAAE,CAACa,MAAM,GAAG,CAAC3B,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC5Dc,EAAE,CAACc,MAAM,GAAG,IAAIhB,IAAI,CAAC,CAAC,CAAC;AACvBE,EAAE,CAACe,OAAO,GAAG,IAAIhB,KAAK,CAAC,CAAC,CAAC;AACzBC,EAAE,CAACgB,KAAK,GAAG,CAAC9B,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACvDc,EAAE,CAACiB,OAAO,GAAG,CAAC/B,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC7Dc,EAAE,CAACkB,OAAO,GAAG,IAAIpB,IAAI,CAAC,CAAC,CAAC;AACxBE,EAAE,CAACmB,QAAQ,GAAG,IAAIpB,KAAK,CAAC,CAAC,CAAC;AAC1B"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js
new file mode 100644
index 0000000000..32b4660a59
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js
@@ -0,0 +1,8 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/
+/**
+ * Equivalent of `setTimeout`, but redirects to WPT's `step_timeout` when it is defined.
+ */
+export const timeout = typeof step_timeout !== 'undefined' ? step_timeout : setTimeout;
+//# sourceMappingURL=timeout.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map
new file mode 100644
index 0000000000..0e8fff6f67
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"timeout.js","names":["timeout","step_timeout","setTimeout"],"sources":["../../../src/common/util/timeout.ts"],"sourcesContent":["/** Defined by WPT. Like `setTimeout`, but applies a timeout multiplier for slow test systems. */\ndeclare const step_timeout: undefined | typeof setTimeout;\n\n/**\n * Equivalent of `setTimeout`, but redirects to WPT's `step_timeout` when it is defined.\n */\nexport const timeout = typeof step_timeout !== 'undefined' ? step_timeout : setTimeout;\n"],"mappings":";AAAA;AAAA;AAGA;AACA;AACA;AACA,OAAO,MAAMA,OAAO,GAAG,OAAOC,YAAY,KAAK,WAAW,GAAGA,YAAY,GAAGC,UAAU"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/types.js b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js
new file mode 100644
index 0000000000..2c224b6d3a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js
@@ -0,0 +1,60 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/
+
+
+
+
+
+
+
+
+
+
+export function assertTypeTrue() {}
+
+/**
+ * Computes the intersection of a set of types, given the union of those types.
+ *
+ * From: https://stackoverflow.com/a/56375136
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// K exhausted
+//# sourceMappingURL=types.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map
new file mode 100644
index 0000000000..084ce36abb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","names":["assertTypeTrue"],"sources":["../../../src/common/util/types.ts"],"sourcesContent":["/** Forces a type to resolve its type definitions, to make it readable/debuggable. */\nexport type ResolveType<T> = T extends object\n ? T extends infer O\n ? { [K in keyof O]: ResolveType<O[K]> }\n : never\n : T;\n\n/** Returns the type `true` iff X and Y are exactly equal */\nexport type TypeEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2\n ? true\n : false;\n\n/* eslint-disable-next-line @typescript-eslint/no-unused-vars */\nexport function assertTypeTrue<T extends true>() {}\n\n/**\n * Computes the intersection of a set of types, given the union of those types.\n *\n * From: https://stackoverflow.com/a/56375136\n */\nexport type UnionToIntersection<U> =\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n\n/** \"Type asserts\" that `X` is a subtype of `Y`. */\ntype EnsureSubtype<X, Y> = X extends Y ? X : never;\n\ntype TupleHeadOr<T, Default> = T extends readonly [infer H, ...(readonly unknown[])] ? H : Default;\ntype TupleTailOr<T, Default> = T extends readonly [unknown, ...infer Tail] ? Tail : Default;\ntype TypeOr<T, Default> = T extends undefined ? Default : T;\n\n/**\n * Zips a key tuple type and a value tuple type together into an object.\n *\n * @template Keys Keys of the resulting object.\n * @template Values Values of the resulting object. If a key corresponds to a `Values` member that\n * is undefined or past the end, it defaults to the corresponding `Defaults` member.\n * @template Defaults Default values. If a key corresponds to a `Defaults` member that is past the\n * end, the default falls back to `undefined`.\n */\nexport type ZipKeysWithValues<\n Keys extends readonly string[],\n Values extends readonly unknown[],\n Defaults extends readonly unknown[]\n> =\n //\n Keys extends readonly [infer KHead, ...infer KTail]\n ? {\n readonly [k in EnsureSubtype<KHead, string>]: TypeOr<\n TupleHeadOr<Values, undefined>,\n TupleHeadOr<Defaults, undefined>\n >;\n } &\n ZipKeysWithValues<\n EnsureSubtype<KTail, readonly string[]>,\n TupleTailOr<Values, []>,\n TupleTailOr<Defaults, []>\n >\n : {}; // K exhausted\n"],"mappings":";AAAA;AAAA;;;;;;;;;;;AAaA,OAAO,SAASA,cAAc,GAAmB,CAAC;;AAElD;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCU"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js
new file mode 100644
index 0000000000..3dfd824b12
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js
@@ -0,0 +1,304 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { Float16Array } from '../../external/petamoriken/float16/float16.js';import { globalTestConfig } from '../framework/test_config.js';import { Logger } from '../internal/logging/logger.js';
+
+import { keysOf } from './data_tables.js';
+import { timeout } from './timeout.js';
+
+/**
+ * Error with arbitrary `extra` data attached, for debugging.
+ * The extra data is omitted if not running the test in debug mode (`?debug=1`).
+ */
+export class ErrorWithExtra extends Error {
+
+
+ /**
+ * `extra` function is only called if in debug mode.
+ * If an `ErrorWithExtra` is passed, its message is used and its extras are passed through.
+ */
+
+
+ constructor(baseOrMessage, newExtra) {
+ const message = typeof baseOrMessage === 'string' ? baseOrMessage : baseOrMessage.message;
+ super(message);
+
+ const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {};
+ this.extra = Logger.globalDebugMode ?
+ { ...oldExtras, ...newExtra() } :
+ { omitted: 'pass ?debug=1' };
+ }
+}
+
+/**
+ * Asserts `condition` is true. Otherwise, throws an `Error` with the provided message.
+ */
+export function assert(condition, msg) {
+ if (!condition) {
+ throw new Error(msg && (typeof msg === 'string' ? msg : msg()));
+ }
+}
+
+/** If the argument is an Error, throw it. Otherwise, pass it back. */
+export function assertOK(value) {
+ if (value instanceof Error) {
+ throw value;
+ }
+ return value;
+}
+
+/**
+ * Resolves if the provided promise rejects; rejects if it does not.
+ */
+export async function assertReject(p, msg) {
+ try {
+ await p;
+ unreachable(msg);
+ } catch (ex) {
+
+ // Assertion OK
+ }}
+
+/**
+ * Assert this code is unreachable. Unconditionally throws an `Error`.
+ */
+export function unreachable(msg) {
+ throw new Error(msg);
+}
+
+/**
+ * The `performance` interface.
+ * It is available in all browsers, but it is not in scope by default in Node.
+ */
+const perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance;
+
+/**
+ * Calls the appropriate `performance.now()` depending on whether running in a browser or Node.
+ */
+export function now() {
+ return perf.now();
+}
+
+/**
+ * Returns a promise which resolves after the specified time.
+ */
+export function resolveOnTimeout(ms) {
+ return new Promise((resolve) => {
+ timeout(() => {
+ resolve();
+ }, ms);
+ });
+}
+
+export class PromiseTimeoutError extends Error {}
+
+/**
+ * Returns a promise which rejects after the specified time.
+ */
+export function rejectOnTimeout(ms, msg) {
+ return new Promise((_resolve, reject) => {
+ timeout(() => {
+ reject(new PromiseTimeoutError(msg));
+ }, ms);
+ });
+}
+
+/**
+ * Takes a promise `p`, and returns a new one which rejects if `p` takes too long,
+ * and otherwise passes the result through.
+ */
+export function raceWithRejectOnTimeout(p, ms, msg) {
+ if (globalTestConfig.noRaceWithRejectOnTimeout) {
+ return p;
+ }
+ // Setup a promise that will reject after `ms` milliseconds. We cancel this timeout when
+ // `p` is finalized, so the JavaScript VM doesn't hang around waiting for the timer to
+ // complete, once the test runner has finished executing the tests.
+ const timeoutPromise = new Promise((_resolve, reject) => {
+ const handle = timeout(() => {
+ reject(new PromiseTimeoutError(msg));
+ }, ms);
+ p = p.finally(() => clearTimeout(handle));
+ });
+ return Promise.race([p, timeoutPromise]);
+}
+
+/**
+ * Takes a promise `p` and returns a new one which rejects if `p` resolves or rejects,
+ * and otherwise resolves after the specified time.
+ */
+export function assertNotSettledWithinTime(
+p,
+ms,
+msg)
+{
+ // Rejects regardless of whether p resolves or rejects.
+ const rejectWhenSettled = p.then(() => Promise.reject(new Error(msg)));
+ // Resolves after `ms` milliseconds.
+ const timeoutPromise = new Promise((resolve) => {
+ const handle = timeout(() => {
+ resolve(undefined);
+ }, ms);
+ p.finally(() => clearTimeout(handle));
+ });
+ return Promise.race([rejectWhenSettled, timeoutPromise]);
+}
+
+/**
+ * Returns a `Promise.reject()`, but also registers a dummy `.catch()` handler so it doesn't count
+ * as an uncaught promise rejection in the runtime.
+ */
+export function rejectWithoutUncaught(err) {
+ const p = Promise.reject(err);
+ // Suppress uncaught promise rejection.
+ p.catch(() => {});
+ return p;
+}
+
+/**
+ * Makes a copy of a JS `object`, with the keys reordered into sorted order.
+ */
+export function sortObjectByKey(v) {
+ const sortedObject = {};
+ for (const k of Object.keys(v).sort()) {
+ sortedObject[k] = v[k];
+ }
+ return sortedObject;
+}
+
+/**
+ * Determines whether two JS values are equal, recursing into objects and arrays.
+ * NaN is treated specially, such that `objectEquals(NaN, NaN)`.
+ */
+export function objectEquals(x, y) {
+ if (typeof x !== 'object' || typeof y !== 'object') {
+ if (typeof x === 'number' && typeof y === 'number' && Number.isNaN(x) && Number.isNaN(y)) {
+ return true;
+ }
+ return x === y;
+ }
+ if (x === null || y === null) return x === y;
+ if (x.constructor !== y.constructor) return false;
+ if (x instanceof Function) return x === y;
+ if (x instanceof RegExp) return x === y;
+ if (x === y || x.valueOf() === y.valueOf()) return true;
+ if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false;
+ if (x instanceof Date) return false;
+ if (!(x instanceof Object)) return false;
+ if (!(y instanceof Object)) return false;
+
+ const x1 = x;
+ const y1 = y;
+ const p = Object.keys(x);
+ return Object.keys(y).every((i) => p.indexOf(i) !== -1) && p.every((i) => objectEquals(x1[i], y1[i]));
+}
+
+/**
+ * Generates a range of values `fn(0)..fn(n-1)`.
+ */
+export function range(n, fn) {
+ return [...new Array(n)].map((_, i) => fn(i));
+}
+
+/**
+ * Generates a range of values `fn(0)..fn(n-1)`.
+ */
+export function* iterRange(n, fn) {
+ for (let i = 0; i < n; ++i) {
+ yield fn(i);
+ }
+}
+
+/** Creates a (reusable) iterable object that maps `f` over `xs`, lazily. */
+export function mapLazy(xs, f) {
+ return {
+ *[Symbol.iterator]() {
+ for (const x of xs) {
+ yield f(x);
+ }
+ }
+ };
+}
+
+const TypedArrayBufferViewInstances = [
+new Uint8Array(),
+new Uint8ClampedArray(),
+new Uint16Array(),
+new Uint32Array(),
+new Int8Array(),
+new Int16Array(),
+new Int32Array(),
+new Float16Array(),
+new Float32Array(),
+new Float64Array()];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+export const kTypedArrayBufferViews =
+
+{
+ ...(() => {
+
+ const result = {};
+ for (const v of TypedArrayBufferViewInstances) {
+ result[v.constructor.name] = v.constructor;
+ }
+ return result;
+ })()
+};
+export const kTypedArrayBufferViewKeys = keysOf(kTypedArrayBufferViews);
+export const kTypedArrayBufferViewConstructors = Object.values(kTypedArrayBufferViews);
+
+function subarrayAsU8(
+buf,
+{ start = 0, length })
+{
+ if (buf instanceof ArrayBuffer) {
+ return new Uint8Array(buf, start, length);
+ } else if (buf instanceof Uint8Array || buf instanceof Uint8ClampedArray) {
+ // Don't wrap in new views if we don't need to.
+ if (start === 0 && (length === undefined || length === buf.byteLength)) {
+ return buf;
+ }
+ }
+ const byteOffset = buf.byteOffset + start * buf.BYTES_PER_ELEMENT;
+ const byteLength =
+ length !== undefined ?
+ length * buf.BYTES_PER_ELEMENT :
+ buf.byteLength - (byteOffset - buf.byteOffset);
+ return new Uint8Array(buf.buffer, byteOffset, byteLength);
+}
+
+/**
+ * Copy a range of bytes from one ArrayBuffer or TypedArray to another.
+ *
+ * `start`/`length` are in elements (or in bytes, if ArrayBuffer).
+ */
+export function memcpy(
+src,
+dst)
+{
+ subarrayAsU8(dst.dst, dst).set(subarrayAsU8(src.src, src));
+}
+//# sourceMappingURL=util.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map
new file mode 100644
index 0000000000..4a8ad3bd50
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"util.js","names":["Float16Array","globalTestConfig","Logger","keysOf","timeout","ErrorWithExtra","Error","constructor","baseOrMessage","newExtra","message","oldExtras","extra","globalDebugMode","omitted","assert","condition","msg","assertOK","value","assertReject","p","unreachable","ex","perf","performance","require","now","resolveOnTimeout","ms","Promise","resolve","PromiseTimeoutError","rejectOnTimeout","_resolve","reject","raceWithRejectOnTimeout","noRaceWithRejectOnTimeout","timeoutPromise","handle","finally","clearTimeout","race","assertNotSettledWithinTime","rejectWhenSettled","then","undefined","rejectWithoutUncaught","err","catch","sortObjectByKey","v","sortedObject","k","Object","keys","sort","objectEquals","x","y","Number","isNaN","Function","RegExp","valueOf","Array","isArray","length","Date","x1","y1","every","i","indexOf","range","n","fn","map","_","iterRange","mapLazy","xs","f","Symbol","iterator","TypedArrayBufferViewInstances","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","Int8Array","Int16Array","Int32Array","Float32Array","Float64Array","kTypedArrayBufferViews","result","name","kTypedArrayBufferViewKeys","kTypedArrayBufferViewConstructors","values","subarrayAsU8","buf","start","ArrayBuffer","byteLength","byteOffset","BYTES_PER_ELEMENT","buffer","memcpy","src","dst","set"],"sources":["../../../src/common/util/util.ts"],"sourcesContent":["import { Float16Array } from '../../external/petamoriken/float16/float16.js';\nimport { globalTestConfig } from '../framework/test_config.js';\nimport { Logger } from '../internal/logging/logger.js';\n\nimport { keysOf } from './data_tables.js';\nimport { timeout } from './timeout.js';\n\n/**\n * Error with arbitrary `extra` data attached, for debugging.\n * The extra data is omitted if not running the test in debug mode (`?debug=1`).\n */\nexport class ErrorWithExtra extends Error {\n readonly extra: { [k: string]: unknown };\n\n /**\n * `extra` function is only called if in debug mode.\n * If an `ErrorWithExtra` is passed, its message is used and its extras are passed through.\n */\n constructor(message: string, extra: () => {});\n constructor(base: ErrorWithExtra, newExtra: () => {});\n constructor(baseOrMessage: string | ErrorWithExtra, newExtra: () => {}) {\n const message = typeof baseOrMessage === 'string' ? baseOrMessage : baseOrMessage.message;\n super(message);\n\n const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {};\n this.extra = Logger.globalDebugMode\n ? { ...oldExtras, ...newExtra() }\n : { omitted: 'pass ?debug=1' };\n }\n}\n\n/**\n * Asserts `condition` is true. Otherwise, throws an `Error` with the provided message.\n */\nexport function assert(condition: boolean, msg?: string | (() => string)): asserts condition {\n if (!condition) {\n throw new Error(msg && (typeof msg === 'string' ? msg : msg()));\n }\n}\n\n/** If the argument is an Error, throw it. Otherwise, pass it back. */\nexport function assertOK<T>(value: Error | T): T {\n if (value instanceof Error) {\n throw value;\n }\n return value;\n}\n\n/**\n * Resolves if the provided promise rejects; rejects if it does not.\n */\nexport async function assertReject(p: Promise<unknown>, msg?: string): Promise<void> {\n try {\n await p;\n unreachable(msg);\n } catch (ex) {\n // Assertion OK\n }\n}\n\n/**\n * Assert this code is unreachable. Unconditionally throws an `Error`.\n */\nexport function unreachable(msg?: string): never {\n throw new Error(msg);\n}\n\n/**\n * The `performance` interface.\n * It is available in all browsers, but it is not in scope by default in Node.\n */\nconst perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance;\n\n/**\n * Calls the appropriate `performance.now()` depending on whether running in a browser or Node.\n */\nexport function now(): number {\n return perf.now();\n}\n\n/**\n * Returns a promise which resolves after the specified time.\n */\nexport function resolveOnTimeout(ms: number): Promise<void> {\n return new Promise(resolve => {\n timeout(() => {\n resolve();\n }, ms);\n });\n}\n\nexport class PromiseTimeoutError extends Error {}\n\n/**\n * Returns a promise which rejects after the specified time.\n */\nexport function rejectOnTimeout(ms: number, msg: string): Promise<never> {\n return new Promise((_resolve, reject) => {\n timeout(() => {\n reject(new PromiseTimeoutError(msg));\n }, ms);\n });\n}\n\n/**\n * Takes a promise `p`, and returns a new one which rejects if `p` takes too long,\n * and otherwise passes the result through.\n */\nexport function raceWithRejectOnTimeout<T>(p: Promise<T>, ms: number, msg: string): Promise<T> {\n if (globalTestConfig.noRaceWithRejectOnTimeout) {\n return p;\n }\n // Setup a promise that will reject after `ms` milliseconds. We cancel this timeout when\n // `p` is finalized, so the JavaScript VM doesn't hang around waiting for the timer to\n // complete, once the test runner has finished executing the tests.\n const timeoutPromise = new Promise((_resolve, reject) => {\n const handle = timeout(() => {\n reject(new PromiseTimeoutError(msg));\n }, ms);\n p = p.finally(() => clearTimeout(handle));\n });\n return Promise.race([p, timeoutPromise]) as Promise<T>;\n}\n\n/**\n * Takes a promise `p` and returns a new one which rejects if `p` resolves or rejects,\n * and otherwise resolves after the specified time.\n */\nexport function assertNotSettledWithinTime(\n p: Promise<unknown>,\n ms: number,\n msg: string\n): Promise<undefined> {\n // Rejects regardless of whether p resolves or rejects.\n const rejectWhenSettled = p.then(() => Promise.reject(new Error(msg)));\n // Resolves after `ms` milliseconds.\n const timeoutPromise = new Promise<undefined>(resolve => {\n const handle = timeout(() => {\n resolve(undefined);\n }, ms);\n p.finally(() => clearTimeout(handle));\n });\n return Promise.race([rejectWhenSettled, timeoutPromise]);\n}\n\n/**\n * Returns a `Promise.reject()`, but also registers a dummy `.catch()` handler so it doesn't count\n * as an uncaught promise rejection in the runtime.\n */\nexport function rejectWithoutUncaught<T>(err: unknown): Promise<T> {\n const p = Promise.reject(err);\n // Suppress uncaught promise rejection.\n p.catch(() => {});\n return p;\n}\n\n/**\n * Makes a copy of a JS `object`, with the keys reordered into sorted order.\n */\nexport function sortObjectByKey(v: { [k: string]: unknown }): { [k: string]: unknown } {\n const sortedObject: { [k: string]: unknown } = {};\n for (const k of Object.keys(v).sort()) {\n sortedObject[k] = v[k];\n }\n return sortedObject;\n}\n\n/**\n * Determines whether two JS values are equal, recursing into objects and arrays.\n * NaN is treated specially, such that `objectEquals(NaN, NaN)`.\n */\nexport function objectEquals(x: unknown, y: unknown): boolean {\n if (typeof x !== 'object' || typeof y !== 'object') {\n if (typeof x === 'number' && typeof y === 'number' && Number.isNaN(x) && Number.isNaN(y)) {\n return true;\n }\n return x === y;\n }\n if (x === null || y === null) return x === y;\n if (x.constructor !== y.constructor) return false;\n if (x instanceof Function) return x === y;\n if (x instanceof RegExp) return x === y;\n if (x === y || x.valueOf() === y.valueOf()) return true;\n if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false;\n if (x instanceof Date) return false;\n if (!(x instanceof Object)) return false;\n if (!(y instanceof Object)) return false;\n\n const x1 = x as { [k: string]: unknown };\n const y1 = y as { [k: string]: unknown };\n const p = Object.keys(x);\n return Object.keys(y).every(i => p.indexOf(i) !== -1) && p.every(i => objectEquals(x1[i], y1[i]));\n}\n\n/**\n * Generates a range of values `fn(0)..fn(n-1)`.\n */\nexport function range<T>(n: number, fn: (i: number) => T): T[] {\n return [...new Array(n)].map((_, i) => fn(i));\n}\n\n/**\n * Generates a range of values `fn(0)..fn(n-1)`.\n */\nexport function* iterRange<T>(n: number, fn: (i: number) => T): Iterable<T> {\n for (let i = 0; i < n; ++i) {\n yield fn(i);\n }\n}\n\n/** Creates a (reusable) iterable object that maps `f` over `xs`, lazily. */\nexport function mapLazy<T, R>(xs: Iterable<T>, f: (x: T) => R): Iterable<R> {\n return {\n *[Symbol.iterator]() {\n for (const x of xs) {\n yield f(x);\n }\n },\n };\n}\n\nconst TypedArrayBufferViewInstances = [\n new Uint8Array(),\n new Uint8ClampedArray(),\n new Uint16Array(),\n new Uint32Array(),\n new Int8Array(),\n new Int16Array(),\n new Int32Array(),\n new Float16Array(),\n new Float32Array(),\n new Float64Array(),\n] as const;\n\nexport type TypedArrayBufferView = typeof TypedArrayBufferViewInstances[number];\n\nexport type TypedArrayBufferViewConstructor<\n A extends TypedArrayBufferView = TypedArrayBufferView\n> = {\n // Interface copied from Uint8Array, and made generic.\n readonly prototype: A;\n readonly BYTES_PER_ELEMENT: number;\n\n new (): A;\n new (elements: Iterable<number>): A;\n new (array: ArrayLike<number> | ArrayBufferLike): A;\n new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): A;\n new (length: number): A;\n\n from(arrayLike: ArrayLike<number>): A;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): A;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): A;\n of(...items: number[]): A;\n};\n\nexport const kTypedArrayBufferViews: {\n readonly [k: string]: TypedArrayBufferViewConstructor;\n} = {\n ...(() => {\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const result: { [k: string]: any } = {};\n for (const v of TypedArrayBufferViewInstances) {\n result[v.constructor.name] = v.constructor;\n }\n return result;\n })(),\n};\nexport const kTypedArrayBufferViewKeys = keysOf(kTypedArrayBufferViews);\nexport const kTypedArrayBufferViewConstructors = Object.values(kTypedArrayBufferViews);\n\nfunction subarrayAsU8(\n buf: ArrayBuffer | TypedArrayBufferView,\n { start = 0, length }: { start?: number; length?: number }\n): Uint8Array | Uint8ClampedArray {\n if (buf instanceof ArrayBuffer) {\n return new Uint8Array(buf, start, length);\n } else if (buf instanceof Uint8Array || buf instanceof Uint8ClampedArray) {\n // Don't wrap in new views if we don't need to.\n if (start === 0 && (length === undefined || length === buf.byteLength)) {\n return buf;\n }\n }\n const byteOffset = buf.byteOffset + start * buf.BYTES_PER_ELEMENT;\n const byteLength =\n length !== undefined\n ? length * buf.BYTES_PER_ELEMENT\n : buf.byteLength - (byteOffset - buf.byteOffset);\n return new Uint8Array(buf.buffer, byteOffset, byteLength);\n}\n\n/**\n * Copy a range of bytes from one ArrayBuffer or TypedArray to another.\n *\n * `start`/`length` are in elements (or in bytes, if ArrayBuffer).\n */\nexport function memcpy(\n src: { src: ArrayBuffer | TypedArrayBufferView; start?: number; length?: number },\n dst: { dst: ArrayBuffer | TypedArrayBufferView; start?: number }\n): void {\n subarrayAsU8(dst.dst, dst).set(subarrayAsU8(src.src, src));\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,YAAY,QAAQ,+CAA+C,CAC5E,SAASC,gBAAgB,QAAQ,6BAA6B,CAC9D,SAASC,MAAM,QAAQ,+BAA+B;;AAEtD,SAASC,MAAM,QAAQ,kBAAkB;AACzC,SAASC,OAAO,QAAQ,cAAc;;AAEtC;AACA;AACA;AACA;AACA,OAAO,MAAMC,cAAc,SAASC,KAAK,CAAC;;;EAGxC;AACF;AACA;AACA;;;EAGEC,WAAW,CAACC,aAAsC,EAAEC,QAAkB,EAAE;IACtE,MAAMC,OAAO,GAAG,OAAOF,aAAa,KAAK,QAAQ,GAAGA,aAAa,GAAGA,aAAa,CAACE,OAAO;IACzF,KAAK,CAACA,OAAO,CAAC;;IAEd,MAAMC,SAAS,GAAGH,aAAa,YAAYH,cAAc,GAAGG,aAAa,CAACI,KAAK,GAAG,CAAC,CAAC;IACpF,IAAI,CAACA,KAAK,GAAGV,MAAM,CAACW,eAAe;IAC/B,EAAE,GAAGF,SAAS,EAAE,GAAGF,QAAQ,EAAE,CAAC,CAAC;IAC/B,EAAEK,OAAO,EAAE,eAAe,CAAC,CAAC;EAClC;AACF;;AAEA;AACA;AACA;AACA,OAAO,SAASC,MAAM,CAACC,SAAkB,EAAEC,GAA6B,EAAqB;EAC3F,IAAI,CAACD,SAAS,EAAE;IACd,MAAM,IAAIV,KAAK,CAACW,GAAG,KAAK,OAAOA,GAAG,KAAK,QAAQ,GAAGA,GAAG,GAAGA,GAAG,EAAE,CAAC,CAAC;EACjE;AACF;;AAEA;AACA,OAAO,SAASC,QAAQ,CAAIC,KAAgB,EAAK;EAC/C,IAAIA,KAAK,YAAYb,KAAK,EAAE;IAC1B,MAAMa,KAAK;EACb;EACA,OAAOA,KAAK;AACd;;AAEA;AACA;AACA;AACA,OAAO,eAAeC,YAAY,CAACC,CAAmB,EAAEJ,GAAY,EAAiB;EACnF,IAAI;IACF,MAAMI,CAAC;IACPC,WAAW,CAACL,GAAG,CAAC;EAClB,CAAC,CAAC,OAAOM,EAAE,EAAE;;IACX;EAAA,CAEJ;;AAEA;AACA;AACA;AACA,OAAO,SAASD,WAAW,CAACL,GAAY,EAAS;EAC/C,MAAM,IAAIX,KAAK,CAACW,GAAG,CAAC;AACtB;;AAEA;AACA;AACA;AACA;AACA,MAAMO,IAAI,GAAG,OAAOC,WAAW,KAAK,WAAW,GAAGA,WAAW,GAAGC,OAAO,CAAC,YAAY,CAAC,CAACD,WAAW;;AAEjG;AACA;AACA;AACA,OAAO,SAASE,GAAG,GAAW;EAC5B,OAAOH,IAAI,CAACG,GAAG,EAAE;AACnB;;AAEA;AACA;AACA;AACA,OAAO,SAASC,gBAAgB,CAACC,EAAU,EAAiB;EAC1D,OAAO,IAAIC,OAAO,CAAC,CAAAC,OAAO,KAAI;IAC5B3B,OAAO,CAAC,MAAM;MACZ2B,OAAO,EAAE;IACX,CAAC,EAAEF,EAAE,CAAC;EACR,CAAC,CAAC;AACJ;;AAEA,OAAO,MAAMG,mBAAmB,SAAS1B,KAAK,CAAC;;AAE/C;AACA;AACA;AACA,OAAO,SAAS2B,eAAe,CAACJ,EAAU,EAAEZ,GAAW,EAAkB;EACvE,OAAO,IAAIa,OAAO,CAAC,CAACI,QAAQ,EAAEC,MAAM,KAAK;IACvC/B,OAAO,CAAC,MAAM;MACZ+B,MAAM,CAAC,IAAIH,mBAAmB,CAACf,GAAG,CAAC,CAAC;IACtC,CAAC,EAAEY,EAAE,CAAC;EACR,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASO,uBAAuB,CAAIf,CAAa,EAAEQ,EAAU,EAAEZ,GAAW,EAAc;EAC7F,IAAIhB,gBAAgB,CAACoC,yBAAyB,EAAE;IAC9C,OAAOhB,CAAC;EACV;EACA;EACA;EACA;EACA,MAAMiB,cAAc,GAAG,IAAIR,OAAO,CAAC,CAACI,QAAQ,EAAEC,MAAM,KAAK;IACvD,MAAMI,MAAM,GAAGnC,OAAO,CAAC,MAAM;MAC3B+B,MAAM,CAAC,IAAIH,mBAAmB,CAACf,GAAG,CAAC,CAAC;IACtC,CAAC,EAAEY,EAAE,CAAC;IACNR,CAAC,GAAGA,CAAC,CAACmB,OAAO,CAAC,MAAMC,YAAY,CAACF,MAAM,CAAC,CAAC;EAC3C,CAAC,CAAC;EACF,OAAOT,OAAO,CAACY,IAAI,CAAC,CAACrB,CAAC,EAAEiB,cAAc,CAAC,CAAC;AAC1C;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASK,0BAA0B;AACxCtB,CAAmB;AACnBQ,EAAU;AACVZ,GAAW;AACS;EACpB;EACA,MAAM2B,iBAAiB,GAAGvB,CAAC,CAACwB,IAAI,CAAC,MAAMf,OAAO,CAACK,MAAM,CAAC,IAAI7B,KAAK,CAACW,GAAG,CAAC,CAAC,CAAC;EACtE;EACA,MAAMqB,cAAc,GAAG,IAAIR,OAAO,CAAY,CAAAC,OAAO,KAAI;IACvD,MAAMQ,MAAM,GAAGnC,OAAO,CAAC,MAAM;MAC3B2B,OAAO,CAACe,SAAS,CAAC;IACpB,CAAC,EAAEjB,EAAE,CAAC;IACNR,CAAC,CAACmB,OAAO,CAAC,MAAMC,YAAY,CAACF,MAAM,CAAC,CAAC;EACvC,CAAC,CAAC;EACF,OAAOT,OAAO,CAACY,IAAI,CAAC,CAACE,iBAAiB,EAAEN,cAAc,CAAC,CAAC;AAC1D;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASS,qBAAqB,CAAIC,GAAY,EAAc;EACjE,MAAM3B,CAAC,GAAGS,OAAO,CAACK,MAAM,CAACa,GAAG,CAAC;EAC7B;EACA3B,CAAC,CAAC4B,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;EACjB,OAAO5B,CAAC;AACV;;AAEA;AACA;AACA;AACA,OAAO,SAAS6B,eAAe,CAACC,CAA2B,EAA4B;EACrF,MAAMC,YAAsC,GAAG,CAAC,CAAC;EACjD,KAAK,MAAMC,CAAC,IAAIC,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC,CAACK,IAAI,EAAE,EAAE;IACrCJ,YAAY,CAACC,CAAC,CAAC,GAAGF,CAAC,CAACE,CAAC,CAAC;EACxB;EACA,OAAOD,YAAY;AACrB;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASK,YAAY,CAACC,CAAU,EAAEC,CAAU,EAAW;EAC5D,IAAI,OAAOD,CAAC,KAAK,QAAQ,IAAI,OAAOC,CAAC,KAAK,QAAQ,EAAE;IAClD,IAAI,OAAOD,CAAC,KAAK,QAAQ,IAAI,OAAOC,CAAC,KAAK,QAAQ,IAAIC,MAAM,CAACC,KAAK,CAACH,CAAC,CAAC,IAAIE,MAAM,CAACC,KAAK,CAACF,CAAC,CAAC,EAAE;MACxF,OAAO,IAAI;IACb;IACA,OAAOD,CAAC,KAAKC,CAAC;EAChB;EACA,IAAID,CAAC,KAAK,IAAI,IAAIC,CAAC,KAAK,IAAI,EAAE,OAAOD,CAAC,KAAKC,CAAC;EAC5C,IAAID,CAAC,CAACnD,WAAW,KAAKoD,CAAC,CAACpD,WAAW,EAAE,OAAO,KAAK;EACjD,IAAImD,CAAC,YAAYI,QAAQ,EAAE,OAAOJ,CAAC,KAAKC,CAAC;EACzC,IAAID,CAAC,YAAYK,MAAM,EAAE,OAAOL,CAAC,KAAKC,CAAC;EACvC,IAAID,CAAC,KAAKC,CAAC,IAAID,CAAC,CAACM,OAAO,EAAE,KAAKL,CAAC,CAACK,OAAO,EAAE,EAAE,OAAO,IAAI;EACvD,IAAIC,KAAK,CAACC,OAAO,CAACR,CAAC,CAAC,IAAIO,KAAK,CAACC,OAAO,CAACP,CAAC,CAAC,IAAID,CAAC,CAACS,MAAM,KAAKR,CAAC,CAACQ,MAAM,EAAE,OAAO,KAAK;EAC/E,IAAIT,CAAC,YAAYU,IAAI,EAAE,OAAO,KAAK;EACnC,IAAI,EAAEV,CAAC,YAAYJ,MAAM,CAAC,EAAE,OAAO,KAAK;EACxC,IAAI,EAAEK,CAAC,YAAYL,MAAM,CAAC,EAAE,OAAO,KAAK;;EAExC,MAAMe,EAAE,GAAGX,CAA6B;EACxC,MAAMY,EAAE,GAAGX,CAA6B;EACxC,MAAMtC,CAAC,GAAGiC,MAAM,CAACC,IAAI,CAACG,CAAC,CAAC;EACxB,OAAOJ,MAAM,CAACC,IAAI,CAACI,CAAC,CAAC,CAACY,KAAK,CAAC,CAAAC,CAAC,KAAInD,CAAC,CAACoD,OAAO,CAACD,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAInD,CAAC,CAACkD,KAAK,CAAC,CAAAC,CAAC,KAAIf,YAAY,CAACY,EAAE,CAACG,CAAC,CAAC,EAAEF,EAAE,CAACE,CAAC,CAAC,CAAC,CAAC;AACnG;;AAEA;AACA;AACA;AACA,OAAO,SAASE,KAAK,CAAIC,CAAS,EAAEC,EAAoB,EAAO;EAC7D,OAAO,CAAC,GAAG,IAAIX,KAAK,CAACU,CAAC,CAAC,CAAC,CAACE,GAAG,CAAC,CAACC,CAAC,EAAEN,CAAC,KAAKI,EAAE,CAACJ,CAAC,CAAC,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,OAAO,UAAUO,SAAS,CAAIJ,CAAS,EAAEC,EAAoB,EAAe;EAC1E,KAAK,IAAIJ,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGG,CAAC,EAAE,EAAEH,CAAC,EAAE;IAC1B,MAAMI,EAAE,CAACJ,CAAC,CAAC;EACb;AACF;;AAEA;AACA,OAAO,SAASQ,OAAO,CAAOC,EAAe,EAAEC,CAAc,EAAe;EAC1E,OAAO;IACL,EAAEC,MAAM,CAACC,QAAQ,IAAI;MACnB,KAAK,MAAM1B,CAAC,IAAIuB,EAAE,EAAE;QAClB,MAAMC,CAAC,CAACxB,CAAC,CAAC;MACZ;IACF;EACF,CAAC;AACH;;AAEA,MAAM2B,6BAA6B,GAAG;AACpC,IAAIC,UAAU,EAAE;AAChB,IAAIC,iBAAiB,EAAE;AACvB,IAAIC,WAAW,EAAE;AACjB,IAAIC,WAAW,EAAE;AACjB,IAAIC,SAAS,EAAE;AACf,IAAIC,UAAU,EAAE;AAChB,IAAIC,UAAU,EAAE;AAChB,IAAI5F,YAAY,EAAE;AAClB,IAAI6F,YAAY,EAAE;AAClB,IAAIC,YAAY,EAAE,CACV;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBV,OAAO,MAAMC,sBAEZ;;AAAG;EACF,GAAG,CAAC,MAAM;;IAER,MAAMC,MAA4B,GAAG,CAAC,CAAC;IACvC,KAAK,MAAM7C,CAAC,IAAIkC,6BAA6B,EAAE;MAC7CW,MAAM,CAAC7C,CAAC,CAAC5C,WAAW,CAAC0F,IAAI,CAAC,GAAG9C,CAAC,CAAC5C,WAAW;IAC5C;IACA,OAAOyF,MAAM;EACf,CAAC;AACH,CAAC;AACD,OAAO,MAAME,yBAAyB,GAAG/F,MAAM,CAAC4F,sBAAsB,CAAC;AACvE,OAAO,MAAMI,iCAAiC,GAAG7C,MAAM,CAAC8C,MAAM,CAACL,sBAAsB,CAAC;;AAEtF,SAASM,YAAY;AACnBC,GAAuC;AACvC,EAAEC,KAAK,GAAG,CAAC,EAAEpC,MAAM,CAAsC,CAAC;AAC1B;EAChC,IAAImC,GAAG,YAAYE,WAAW,EAAE;IAC9B,OAAO,IAAIlB,UAAU,CAACgB,GAAG,EAAEC,KAAK,EAAEpC,MAAM,CAAC;EAC3C,CAAC,MAAM,IAAImC,GAAG,YAAYhB,UAAU,IAAIgB,GAAG,YAAYf,iBAAiB,EAAE;IACxE;IACA,IAAIgB,KAAK,KAAK,CAAC,KAAKpC,MAAM,KAAKrB,SAAS,IAAIqB,MAAM,KAAKmC,GAAG,CAACG,UAAU,CAAC,EAAE;MACtE,OAAOH,GAAG;IACZ;EACF;EACA,MAAMI,UAAU,GAAGJ,GAAG,CAACI,UAAU,GAAGH,KAAK,GAAGD,GAAG,CAACK,iBAAiB;EACjE,MAAMF,UAAU;EACdtC,MAAM,KAAKrB,SAAS;EAChBqB,MAAM,GAAGmC,GAAG,CAACK,iBAAiB;EAC9BL,GAAG,CAACG,UAAU,IAAIC,UAAU,GAAGJ,GAAG,CAACI,UAAU,CAAC;EACpD,OAAO,IAAIpB,UAAU,CAACgB,GAAG,CAACM,MAAM,EAAEF,UAAU,EAAED,UAAU,CAAC;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,MAAM;AACpBC,GAAiF;AACjFC,GAAgE;AAC1D;EACNV,YAAY,CAACU,GAAG,CAACA,GAAG,EAAEA,GAAG,CAAC,CAACC,GAAG,CAACX,YAAY,CAACS,GAAG,CAACA,GAAG,EAAEA,GAAG,CAAC,CAAC;AAC5D"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js
new file mode 100644
index 0000000000..c2fc1f596d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js
@@ -0,0 +1,25 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { timeout } from './timeout.js'; // Copied from https://github.com/web-platform-tests/wpt/blob/master/common/reftest-wait.js
+
+/**
+ * Remove the `reftest-wait` class on the document element.
+ * The reftest runner will wait with taking a screenshot while
+ * this class is present.
+ *
+ * See https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs
+ */
+export function takeScreenshot() {
+ document.documentElement.classList.remove('reftest-wait');
+}
+
+/**
+ * Call `takeScreenshot()` after a delay of at least `ms` milliseconds.
+ * @param {number} ms - milliseconds
+ */
+export function takeScreenshotDelayed(ms) {
+ timeout(() => {
+ takeScreenshot();
+ }, ms);
+}
+//# sourceMappingURL=wpt_reftest_wait.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map
new file mode 100644
index 0000000000..a231c5f611
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"wpt_reftest_wait.js","names":["timeout","takeScreenshot","document","documentElement","classList","remove","takeScreenshotDelayed","ms"],"sources":["../../../src/common/util/wpt_reftest_wait.ts"],"sourcesContent":["import { timeout } from './timeout.js';\n\n// Copied from https://github.com/web-platform-tests/wpt/blob/master/common/reftest-wait.js\n\n/**\n * Remove the `reftest-wait` class on the document element.\n * The reftest runner will wait with taking a screenshot while\n * this class is present.\n *\n * See https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs\n */\nexport function takeScreenshot() {\n document.documentElement.classList.remove('reftest-wait');\n}\n\n/**\n * Call `takeScreenshot()` after a delay of at least `ms` milliseconds.\n * @param {number} ms - milliseconds\n */\nexport function takeScreenshotDelayed(ms: number) {\n timeout(() => {\n takeScreenshot();\n }, ms);\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,OAAO,QAAQ,cAAc,CAAC,CAEvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAc,GAAG;EAC/BC,QAAQ,CAACC,eAAe,CAACC,SAAS,CAACC,MAAM,CAAC,cAAc,CAAC;AAC3D;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqB,CAACC,EAAU,EAAE;EAChDP,OAAO,CAAC,MAAM;IACZC,cAAc,EAAE;EAClB,CAAC,EAAEM,EAAE,CAAC;AACR"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js
new file mode 100644
index 0000000000..d78ce8de82
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js
@@ -0,0 +1,4 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/export {};
+//# sourceMappingURL=float16.d.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js.map b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js.map
new file mode 100644
index 0000000000..ad7929e6a4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.d.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"float16.d.js","names":[],"sources":["../../../../src/external/petamoriken/float16/float16.d.ts"],"sourcesContent":["/**\n * A typed array of 16-bit float values. The contents are initialized to 0. If the requested number\n * of bytes could not be allocated an exception is raised.\n */\nexport interface Float16Array {\n /**\n * The size in bytes of each element in the array.\n */\n readonly BYTES_PER_ELEMENT: number;\n\n /**\n * The ArrayBuffer instance referenced by the array.\n */\n readonly buffer: ArrayBufferLike;\n\n /**\n * The length in bytes of the array.\n */\n readonly byteLength: number;\n\n /**\n * The offset in bytes of the array.\n */\n readonly byteOffset: number;\n\n [Symbol.iterator](): IterableIterator<number>;\n\n /**\n * Returns an array of key, value pairs for every entry in the array\n */\n entries(): IterableIterator<[number, number]>;\n\n /**\n * Returns an list of keys in the array\n */\n keys(): IterableIterator<number>;\n\n /**\n * Returns an list of values in the array\n */\n values(): IterableIterator<number>;\n\n /**\n * Returns the item located at the specified index.\n * @param index The zero-based index of the desired code unit. A negative index will count back from the last item.\n */\n at(index: number): number | undefined;\n\n /**\n * Returns the this object after copying a section of the array identified by start and end\n * to the same array starting at position target\n * @param target If target is negative, it is treated as length+target where length is the\n * length of the array.\n * @param start If start is negative, it is treated as length+start. If end is negative, it\n * is treated as length+end.\n * @param end If not specified, length of the this object is used as its default value.\n */\n copyWithin(target: number, start: number, end?: number): this;\n\n /**\n * Determines whether all the members of an array satisfy the specified test.\n * @param callbackfn A function that accepts up to three arguments. The every method calls\n * the callbackfn function for each element in the array until the callbackfn returns a value\n * which is coercible to the Boolean value false, or until the end of the array.\n * @param thisArg An object to which the this keyword can refer in the callbackfn function.\n * If thisArg is omitted, undefined is used as the this value.\n */\n every(\n callbackfn: (value: number, index: number, array: Float16Array) => unknown,\n thisArg?: any,\n ): boolean;\n\n /**\n * Returns the this object after filling the section identified by start and end with value\n * @param value value to fill array section with\n * @param start index to start filling the array at. If start is negative, it is treated as\n * length+start where length is the length of the array.\n * @param end index to stop filling the array at. If end is negative, it is treated as\n * length+end.\n */\n fill(value: number, start?: number, end?: number): this;\n\n /**\n * Returns the elements of an array that meet the condition specified in a callback function.\n * @param predicate A function that accepts up to three arguments. The filter method calls\n * the predicate function one time for each element in the array.\n * @param thisArg An object to which the this keyword can refer in the predicate function.\n * If thisArg is omitted, undefined is used as the this value.\n */\n filter(\n predicate: (value: number, index: number, array: Float16Array) => any,\n thisArg?: any,\n ): Float16Array;\n\n /**\n * Returns the value of the first element in the array where predicate is true, and undefined\n * otherwise.\n * @param predicate find calls predicate once for each element of the array, in ascending\n * order, until it finds one where predicate returns true. If such an element is found, find\n * immediately returns that element value. Otherwise, find returns undefined.\n * @param thisArg If provided, it will be used as the this value for each invocation of\n * predicate. If it is not provided, undefined is used instead.\n */\n find(\n predicate: (value: number, index: number, obj: Float16Array) => boolean,\n thisArg?: any,\n ): number | undefined;\n\n /**\n * Returns the index of the first element in the array where predicate is true, and -1\n * otherwise.\n * @param predicate find calls predicate once for each element of the array, in ascending\n * order, until it finds one where predicate returns true. If such an element is found,\n * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\n * @param thisArg If provided, it will be used as the this value for each invocation of\n * predicate. If it is not provided, undefined is used instead.\n */\n findIndex(\n predicate: (value: number, index: number, obj: Float16Array) => boolean,\n thisArg?: any,\n ): number;\n\n /**\n * Returns the value of the last element in the array where predicate is true, and undefined\n * otherwise.\n * @param predicate find calls predicate once for each element of the array, in descending\n * order, until it finds one where predicate returns true. If such an element is found, findLast\n * immediately returns that element value. Otherwise, findLast returns undefined.\n * @param thisArg If provided, it will be used as the this value for each invocation of\n * predicate. If it is not provided, undefined is used instead.\n */\n findLast(\n predicate: (value: number, index: number, obj: Float16Array) => boolean,\n thisArg?: any,\n ): number | undefined;\n\n /**\n * Returns the index of the last element in the array where predicate is true, and -1\n * otherwise.\n * @param predicate find calls predicate once for each element of the array, in descending\n * order, until it finds one where predicate returns true. If such an element is found,\n * findLastIndex immediately returns that element index. Otherwise, findLastIndex returns -1.\n * @param thisArg If provided, it will be used as the this value for each invocation of\n * predicate. If it is not provided, undefined is used instead.\n */\n findLastIndex(\n predicate: (value: number, index: number, obj: Float16Array) => boolean,\n thisArg?: any,\n ): number;\n\n /**\n * Performs the specified action for each element in an array.\n * @param callbackfn A function that accepts up to three arguments. forEach calls the\n * callbackfn function one time for each element in the array.\n * @param thisArg An object to which the this keyword can refer in the callbackfn function.\n * If thisArg is omitted, undefined is used as the this value.\n */\n forEach(\n callbackfn: (value: number, index: number, array: Float16Array) => void,\n thisArg?: any,\n ): void;\n\n /**\n * Determines whether an array includes a certain element, returning true or false as appropriate.\n * @param searchElement The element to search for.\n * @param fromIndex The position in this array at which to begin searching for searchElement.\n */\n includes(searchElement: number, fromIndex?: number): boolean;\n\n /**\n * Returns the index of the first occurrence of a value in an array.\n * @param searchElement The value to locate in the array.\n * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\n * search starts at index 0.\n */\n indexOf(searchElement: number, fromIndex?: number): number;\n\n /**\n * Adds all the elements of an array separated by the specified separator string.\n * @param separator A string used to separate one element of an array from the next in the\n * resulting String. If omitted, the array elements are separated with a comma.\n */\n join(separator?: string): string;\n\n /**\n * Returns the index of the last occurrence of a value in an array.\n * @param searchElement The value to locate in the array.\n * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\n * search starts at index 0.\n */\n lastIndexOf(searchElement: number, fromIndex?: number): number;\n\n /**\n * The length of the array.\n */\n readonly length: number;\n\n /**\n * Calls a defined callback function on each element of an array, and returns an array that\n * contains the results.\n * @param callbackfn A function that accepts up to three arguments. The map method calls the\n * callbackfn function one time for each element in the array.\n * @param thisArg An object to which the this keyword can refer in the callbackfn function.\n * If thisArg is omitted, undefined is used as the this value.\n */\n map(\n callbackfn: (value: number, index: number, array: Float16Array) => number,\n thisArg?: any,\n ): Float16Array;\n\n /**\n * Calls the specified callback function for all the elements in an array. The return value of\n * the callback function is the accumulated result, and is provided as an argument in the next\n * call to the callback function.\n * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\n * callbackfn function one time for each element in the array.\n * @param initialValue If initialValue is specified, it is used as the initial value to start\n * the accumulation. The first call to the callbackfn function provides this value as an argument\n * instead of an array value.\n */\n reduce(\n callbackfn: (\n previousValue: number,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => number,\n ): number;\n reduce(\n callbackfn: (\n previousValue: number,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => number,\n initialValue: number,\n ): number;\n reduce<U>(\n callbackfn: (\n previousValue: U,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => U,\n initialValue: U,\n ): U;\n\n /**\n * Calls the specified callback function for all the elements in an array, in descending order.\n * The return value of the callback function is the accumulated result, and is provided as an\n * argument in the next call to the callback function.\n * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\n * the callbackfn function one time for each element in the array.\n * @param initialValue If initialValue is specified, it is used as the initial value to start\n * the accumulation. The first call to the callbackfn function provides this value as an\n * argument instead of an array value.\n */\n reduceRight(\n callbackfn: (\n previousValue: number,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => number,\n ): number;\n reduceRight(\n callbackfn: (\n previousValue: number,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => number,\n initialValue: number,\n ): number;\n reduceRight<U>(\n callbackfn: (\n previousValue: U,\n currentValue: number,\n currentIndex: number,\n array: Float16Array,\n ) => U,\n initialValue: U,\n ): U;\n\n /**\n * Reverses the elements in an Array.\n */\n reverse(): this;\n\n /**\n * Sets a value or an array of values.\n * @param array A typed or untyped array of values to set.\n * @param offset The index in the current array at which the values are to be written.\n */\n set(array: ArrayLike<number>, offset?: number): void;\n\n /**\n * Returns a section of an array.\n * @param start The beginning of the specified portion of the array.\n * @param end The end of the specified portion of the array. This is exclusive of the element at the index 'end'.\n */\n slice(start?: number, end?: number): Float16Array;\n\n /**\n * Determines whether the specified callback function returns true for any element of an array.\n * @param callbackfn A function that accepts up to three arguments. The some method calls\n * the callbackfn function for each element in the array until the callbackfn returns a value\n * which is coercible to the Boolean value true, or until the end of the array.\n * @param thisArg An object to which the this keyword can refer in the callbackfn function.\n * If thisArg is omitted, undefined is used as the this value.\n */\n some(\n callbackfn: (value: number, index: number, array: Float16Array) => unknown,\n thisArg?: any,\n ): boolean;\n\n /**\n * Sorts an array.\n * @param compareFn Function used to determine the order of the elements. It is expected to return\n * a negative value if first argument is less than second argument, zero if they're equal and a positive\n * value otherwise. If omitted, the elements are sorted in ascending.\n */\n sort(compareFn?: (a: number, b: number) => number): this;\n\n /**\n * Gets a new Float16Array view of the ArrayBuffer store for this array, referencing the elements\n * at begin, inclusive, up to end, exclusive.\n * @param begin The index of the beginning of the array.\n * @param end The index of the end of the array.\n */\n subarray(begin?: number, end?: number): Float16Array;\n\n /**\n * Converts a number to a string by using the current locale.\n */\n toLocaleString(): string;\n\n /**\n * Returns a string representation of an array.\n */\n toString(): string;\n\n /**\n * Returns the primitive value of the specified object.\n */\n valueOf(): Float16Array;\n\n readonly [Symbol.toStringTag]: \"Float16Array\";\n\n [index: number]: number;\n}\n\nexport interface Float16ArrayConstructor {\n readonly prototype: Float16Array;\n new (): Float16Array;\n new (length: number): Float16Array;\n new (elements: Iterable<number>): Float16Array;\n new (array: ArrayLike<number> | ArrayBufferLike): Float16Array;\n new (\n buffer: ArrayBufferLike,\n byteOffset: number,\n length?: number,\n ): Float16Array;\n\n /**\n * The size in bytes of each element in the array.\n */\n readonly BYTES_PER_ELEMENT: number;\n\n /**\n * Returns a new array from a set of elements.\n * @param items A set of elements to include in the new array object.\n */\n of(...items: number[]): Float16Array;\n\n /**\n * Creates an array from an array-like or iterable object.\n * @param elements An iterable object to convert to an array.\n */\n from(elements: Iterable<number>): Float16Array;\n\n /**\n * Creates an array from an array-like or iterable object.\n * @param elements An iterable object to convert to an array.\n * @param mapfn A mapping function to call on every element of the array.\n * @param thisArg Value of 'this' used to invoke the mapfn.\n */\n from<T>(\n elements: Iterable<T>,\n mapfn: (v: T, k: number) => number,\n thisArg?: any,\n ): Float16Array;\n\n /**\n * Creates an array from an array-like or iterable object.\n * @param arrayLike An array-like object to convert to an array.\n */\n from(arrayLike: ArrayLike<number>): Float16Array;\n\n /**\n * Creates an array from an array-like or iterable object.\n * @param arrayLike An array-like object to convert to an array.\n * @param mapfn A mapping function to call on every element of the array.\n * @param thisArg Value of 'this' used to invoke the mapfn.\n */\n from<T>(\n arrayLike: ArrayLike<T>,\n mapfn: (v: T, k: number) => number,\n thisArg?: any,\n ): Float16Array;\n}\nexport declare const Float16Array: Float16ArrayConstructor;\n\n/**\n * Returns `true` if the value is a Float16Array instance.\n * @since v3.4.0\n */\nexport declare function isFloat16Array(value: unknown): value is Float16Array;\n\n/**\n * Returns `true` if the value is a type of TypedArray instance that contains Float16Array.\n * @since v3.6.0\n */\nexport declare function isTypedArray(\n value: unknown,\n): value is\n | Uint8Array\n | Uint8ClampedArray\n | Uint16Array\n | Uint32Array\n | Int8Array\n | Int16Array\n | Int32Array\n | Float16Array\n | Float32Array\n | Float64Array\n | BigUint64Array\n | BigInt64Array;\n\n/**\n * Gets the Float16 value at the specified byte offset from the start of the view. There is\n * no alignment constraint; multi-byte values may be fetched from any offset.\n * @param byteOffset The place in the buffer at which the value should be retrieved.\n * @param littleEndian If false or undefined, a big-endian value should be read,\n * otherwise a little-endian value should be read.\n */\nexport declare function getFloat16(\n dataView: DataView,\n byteOffset: number,\n littleEndian?: boolean,\n): number;\n\n/**\n * Stores an Float16 value at the specified byte offset from the start of the view.\n * @param byteOffset The place in the buffer at which the value should be set.\n * @param value The value to set.\n * @param littleEndian If false or undefined, a big-endian value should be written,\n * otherwise a little-endian value should be written.\n */\nexport declare function setFloat16(\n dataView: DataView,\n byteOffset: number,\n value: number,\n littleEndian?: boolean,\n): void;\n\n/**\n * Returns the nearest half-precision float representation of a number.\n * @param x A numeric expression.\n */\nexport declare function hfround(x: number): number;\n"],"mappings":";AAAA;AAAA,G"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js
new file mode 100644
index 0000000000..13314a1d4c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js
@@ -0,0 +1,1229 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /*! @petamoriken/float16 v3.6.6 | MIT License - https://github.com/petamoriken/float16 */const THIS_IS_NOT_AN_OBJECT = "This is not an object";
+const THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = "This is not a Float16Array object";
+const THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY =
+"This constructor is not a subclass of Float16Array";
+const THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT =
+"The constructor property value is not an object";
+const SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT =
+"Species constructor didn't return TypedArray object";
+const DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH =
+"Derived constructor created TypedArray object which was too small length";
+const ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER =
+"Attempting to access detached ArrayBuffer";
+const CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT =
+"Cannot convert undefined or null to object";
+const CANNOT_MIX_BIGINT_AND_OTHER_TYPES =
+"Cannot mix BigInt and other types, use explicit conversions";
+const ITERATOR_PROPERTY_IS_NOT_CALLABLE = "@@iterator property is not callable";
+const REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE =
+"Reduce of empty array with no initial value";
+const OFFSET_IS_OUT_OF_BOUNDS = "Offset is out of bounds";
+
+function uncurryThis(target) {
+ return (thisArg, ...args) => {
+ return ReflectApply(target, thisArg, args);
+ };
+}
+function uncurryThisGetter(target, key) {
+ return uncurryThis(
+ ReflectGetOwnPropertyDescriptor(
+ target,
+ key).
+ get);
+
+}
+const {
+ apply: ReflectApply,
+ construct: ReflectConstruct,
+ defineProperty: ReflectDefineProperty,
+ get: ReflectGet,
+ getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,
+ getPrototypeOf: ReflectGetPrototypeOf,
+ has: ReflectHas,
+ ownKeys: ReflectOwnKeys,
+ set: ReflectSet,
+ setPrototypeOf: ReflectSetPrototypeOf
+} = Reflect;
+const NativeProxy = Proxy;
+const {
+ MAX_SAFE_INTEGER: MAX_SAFE_INTEGER,
+ isFinite: NumberIsFinite,
+ isNaN: NumberIsNaN
+} = Number;
+const {
+ iterator: SymbolIterator,
+ species: SymbolSpecies,
+ toStringTag: SymbolToStringTag,
+ for: SymbolFor
+} = Symbol;
+const NativeObject = Object;
+const {
+ create: ObjectCreate,
+ defineProperty: ObjectDefineProperty,
+ freeze: ObjectFreeze,
+ is: ObjectIs
+} = NativeObject;
+const ObjectPrototype = NativeObject.prototype;
+const ObjectPrototype__lookupGetter__ = ObjectPrototype.__lookupGetter__ ?
+uncurryThis(ObjectPrototype.__lookupGetter__) :
+(object, key) => {
+ if (object == null) {
+ throw NativeTypeError(
+ CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT);
+
+ }
+ let target = NativeObject(object);
+ do {
+ const descriptor = ReflectGetOwnPropertyDescriptor(target, key);
+ if (descriptor !== undefined) {
+ if (ObjectHasOwn(descriptor, "get")) {
+ return descriptor.get;
+ }
+ return;
+ }
+ } while ((target = ReflectGetPrototypeOf(target)) !== null);
+};
+const ObjectHasOwn = NativeObject.hasOwn ||
+uncurryThis(ObjectPrototype.hasOwnProperty);
+const NativeArray = Array;
+const ArrayIsArray = NativeArray.isArray;
+const ArrayPrototype = NativeArray.prototype;
+const ArrayPrototypeJoin = uncurryThis(ArrayPrototype.join);
+const ArrayPrototypePush = uncurryThis(ArrayPrototype.push);
+const ArrayPrototypeToLocaleString = uncurryThis(
+ArrayPrototype.toLocaleString);
+
+const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator];
+const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator);
+const MathTrunc = Math.trunc;
+const NativeArrayBuffer = ArrayBuffer;
+const ArrayBufferIsView = NativeArrayBuffer.isView;
+const ArrayBufferPrototype = NativeArrayBuffer.prototype;
+const ArrayBufferPrototypeSlice = uncurryThis(ArrayBufferPrototype.slice);
+const ArrayBufferPrototypeGetByteLength = uncurryThisGetter(ArrayBufferPrototype, "byteLength");
+const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : null;
+const SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer &&
+uncurryThisGetter(NativeSharedArrayBuffer.prototype, "byteLength");
+const TypedArray = ReflectGetPrototypeOf(Uint8Array);
+const TypedArrayFrom = TypedArray.from;
+const TypedArrayPrototype = TypedArray.prototype;
+const NativeTypedArrayPrototypeSymbolIterator = TypedArrayPrototype[SymbolIterator];
+const TypedArrayPrototypeKeys = uncurryThis(TypedArrayPrototype.keys);
+const TypedArrayPrototypeValues = uncurryThis(
+TypedArrayPrototype.values);
+
+const TypedArrayPrototypeEntries = uncurryThis(
+TypedArrayPrototype.entries);
+
+const TypedArrayPrototypeSet = uncurryThis(TypedArrayPrototype.set);
+const TypedArrayPrototypeReverse = uncurryThis(
+TypedArrayPrototype.reverse);
+
+const TypedArrayPrototypeFill = uncurryThis(TypedArrayPrototype.fill);
+const TypedArrayPrototypeCopyWithin = uncurryThis(
+TypedArrayPrototype.copyWithin);
+
+const TypedArrayPrototypeSort = uncurryThis(TypedArrayPrototype.sort);
+const TypedArrayPrototypeSlice = uncurryThis(TypedArrayPrototype.slice);
+const TypedArrayPrototypeSubarray = uncurryThis(
+TypedArrayPrototype.subarray);
+
+const TypedArrayPrototypeGetBuffer = uncurryThisGetter(
+TypedArrayPrototype,
+"buffer");
+
+const TypedArrayPrototypeGetByteOffset = uncurryThisGetter(
+TypedArrayPrototype,
+"byteOffset");
+
+const TypedArrayPrototypeGetLength = uncurryThisGetter(
+TypedArrayPrototype,
+"length");
+
+const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter(
+TypedArrayPrototype,
+SymbolToStringTag);
+
+const NativeUint16Array = Uint16Array;
+const Uint16ArrayFrom = (...args) => {
+ return ReflectApply(TypedArrayFrom, NativeUint16Array, args);
+};
+const NativeUint32Array = Uint32Array;
+const NativeFloat32Array = Float32Array;
+const ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]());
+const ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next);
+const GeneratorPrototypeNext = uncurryThis(function* () {}().next);
+const IteratorPrototype = ReflectGetPrototypeOf(ArrayIteratorPrototype);
+const DataViewPrototype = DataView.prototype;
+const DataViewPrototypeGetUint16 = uncurryThis(
+DataViewPrototype.getUint16);
+
+const DataViewPrototypeSetUint16 = uncurryThis(
+DataViewPrototype.setUint16);
+
+const NativeTypeError = TypeError;
+const NativeRangeError = RangeError;
+const NativeWeakSet = WeakSet;
+const WeakSetPrototype = NativeWeakSet.prototype;
+const WeakSetPrototypeAdd = uncurryThis(WeakSetPrototype.add);
+const WeakSetPrototypeHas = uncurryThis(WeakSetPrototype.has);
+const NativeWeakMap = WeakMap;
+const WeakMapPrototype = NativeWeakMap.prototype;
+const WeakMapPrototypeGet = uncurryThis(WeakMapPrototype.get);
+const WeakMapPrototypeHas = uncurryThis(WeakMapPrototype.has);
+const WeakMapPrototypeSet = uncurryThis(WeakMapPrototype.set);
+
+const arrayIterators = new NativeWeakMap();
+const SafeIteratorPrototype = ObjectCreate(null, {
+ next: {
+ value: function next() {
+ const arrayIterator = WeakMapPrototypeGet(arrayIterators, this);
+ return ArrayIteratorPrototypeNext(arrayIterator);
+ }
+ },
+ [SymbolIterator]: {
+ value: function values() {
+ return this;
+ }
+ }
+});
+function safeIfNeeded(array) {
+ if (array[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {
+ return array;
+ }
+ const safe = ObjectCreate(SafeIteratorPrototype);
+ WeakMapPrototypeSet(arrayIterators, safe, ArrayPrototypeSymbolIterator(array));
+ return safe;
+}
+const generators = new NativeWeakMap();
+const DummyArrayIteratorPrototype = ObjectCreate(IteratorPrototype, {
+ next: {
+ value: function next() {
+ const generator = WeakMapPrototypeGet(generators, this);
+ return GeneratorPrototypeNext(generator);
+ },
+ writable: true,
+ configurable: true
+ }
+});
+for (const key of ReflectOwnKeys(ArrayIteratorPrototype)) {
+ if (key === "next") {
+ continue;
+ }
+ ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key));
+}
+function wrap(generator) {
+ const dummy = ObjectCreate(DummyArrayIteratorPrototype);
+ WeakMapPrototypeSet(generators, dummy, generator);
+ return dummy;
+}
+
+function isObject(value) {
+ return value !== null && typeof value === "object" ||
+ typeof value === "function";
+}
+function isObjectLike(value) {
+ return value !== null && typeof value === "object";
+}
+function isNativeTypedArray(value) {
+ return TypedArrayPrototypeGetSymbolToStringTag(value) !== undefined;
+}
+function isNativeBigIntTypedArray(value) {
+ const typedArrayName = TypedArrayPrototypeGetSymbolToStringTag(value);
+ return typedArrayName === "BigInt64Array" ||
+ typedArrayName === "BigUint64Array";
+}
+function isArrayBuffer(value) {
+ try {
+ ArrayBufferPrototypeGetByteLength(value);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+function isSharedArrayBuffer(value) {
+ if (NativeSharedArrayBuffer === null) {
+ return false;
+ }
+ try {
+ SharedArrayBufferPrototypeGetByteLength(value);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+function isOrdinaryArray(value) {
+ if (!ArrayIsArray(value)) {
+ return false;
+ }
+ if (value[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {
+ return true;
+ }
+ const iterator = value[SymbolIterator]();
+ return iterator[SymbolToStringTag] === "Array Iterator";
+}
+function isOrdinaryNativeTypedArray(value) {
+ if (!isNativeTypedArray(value)) {
+ return false;
+ }
+ if (value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator) {
+ return true;
+ }
+ const iterator = value[SymbolIterator]();
+ return iterator[SymbolToStringTag] === "Array Iterator";
+}
+function isCanonicalIntegerIndexString(value) {
+ if (typeof value !== "string") {
+ return false;
+ }
+ const number = +value;
+ if (value !== number + "") {
+ return false;
+ }
+ if (!NumberIsFinite(number)) {
+ return false;
+ }
+ return number === MathTrunc(number);
+}
+
+const brand = SymbolFor("__Float16Array__");
+function hasFloat16ArrayBrand(target) {
+ if (!isObjectLike(target)) {
+ return false;
+ }
+ const prototype = ReflectGetPrototypeOf(target);
+ if (!isObjectLike(prototype)) {
+ return false;
+ }
+ const constructor = prototype.constructor;
+ if (constructor === undefined) {
+ return false;
+ }
+ if (!isObject(constructor)) {
+ throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT);
+ }
+ return ReflectHas(constructor, brand);
+}
+
+const buffer = new NativeArrayBuffer(4);
+const floatView = new NativeFloat32Array(buffer);
+const uint32View = new NativeUint32Array(buffer);
+const baseTable = new NativeUint32Array(512);
+const shiftTable = new NativeUint32Array(512);
+for (let i = 0; i < 256; ++i) {
+ const e = i - 127;
+ if (e < -27) {
+ baseTable[i] = 0x0000;
+ baseTable[i | 0x100] = 0x8000;
+ shiftTable[i] = 24;
+ shiftTable[i | 0x100] = 24;
+ } else if (e < -14) {
+ baseTable[i] = 0x0400 >> -e - 14;
+ baseTable[i | 0x100] = 0x0400 >> -e - 14 | 0x8000;
+ shiftTable[i] = -e - 1;
+ shiftTable[i | 0x100] = -e - 1;
+ } else if (e <= 15) {
+ baseTable[i] = e + 15 << 10;
+ baseTable[i | 0x100] = e + 15 << 10 | 0x8000;
+ shiftTable[i] = 13;
+ shiftTable[i | 0x100] = 13;
+ } else if (e < 128) {
+ baseTable[i] = 0x7c00;
+ baseTable[i | 0x100] = 0xfc00;
+ shiftTable[i] = 24;
+ shiftTable[i | 0x100] = 24;
+ } else {
+ baseTable[i] = 0x7c00;
+ baseTable[i | 0x100] = 0xfc00;
+ shiftTable[i] = 13;
+ shiftTable[i | 0x100] = 13;
+ }
+}
+function roundToFloat16Bits(num) {
+ floatView[0] = num;
+ const f = uint32View[0];
+ const e = f >> 23 & 0x1ff;
+ return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]);
+}
+const mantissaTable = new NativeUint32Array(2048);
+const exponentTable = new NativeUint32Array(64);
+const offsetTable = new NativeUint32Array(64);
+for (let i = 1; i < 1024; ++i) {
+ let m = i << 13;
+ let e = 0;
+ while ((m & 0x00800000) === 0) {
+ m <<= 1;
+ e -= 0x00800000;
+ }
+ m &= ~0x00800000;
+ e += 0x38800000;
+ mantissaTable[i] = m | e;
+}
+for (let i = 1024; i < 2048; ++i) {
+ mantissaTable[i] = 0x38000000 + (i - 1024 << 13);
+}
+for (let i = 1; i < 31; ++i) {
+ exponentTable[i] = i << 23;
+}
+exponentTable[31] = 0x47800000;
+exponentTable[32] = 0x80000000;
+for (let i = 33; i < 63; ++i) {
+ exponentTable[i] = 0x80000000 + (i - 32 << 23);
+}
+exponentTable[63] = 0xc7800000;
+for (let i = 1; i < 64; ++i) {
+ if (i !== 32) {
+ offsetTable[i] = 1024;
+ }
+}
+function convertToNumber(float16bits) {
+ const m = float16bits >> 10;
+ uint32View[0] = mantissaTable[offsetTable[m] + (float16bits & 0x3ff)] + exponentTable[m];
+ return floatView[0];
+}
+
+function ToIntegerOrInfinity(target) {
+ const number = +target;
+ if (NumberIsNaN(number) || number === 0) {
+ return 0;
+ }
+ return MathTrunc(number);
+}
+function ToLength(target) {
+ const length = ToIntegerOrInfinity(target);
+ if (length < 0) {
+ return 0;
+ }
+ return length < MAX_SAFE_INTEGER ?
+ length :
+ MAX_SAFE_INTEGER;
+}
+function SpeciesConstructor(target, defaultConstructor) {
+ if (!isObject(target)) {
+ throw NativeTypeError(THIS_IS_NOT_AN_OBJECT);
+ }
+ const constructor = target.constructor;
+ if (constructor === undefined) {
+ return defaultConstructor;
+ }
+ if (!isObject(constructor)) {
+ throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT);
+ }
+ const species = constructor[SymbolSpecies];
+ if (species == null) {
+ return defaultConstructor;
+ }
+ return species;
+}
+function IsDetachedBuffer(buffer) {
+ if (isSharedArrayBuffer(buffer)) {
+ return false;
+ }
+ try {
+ ArrayBufferPrototypeSlice(buffer, 0, 0);
+ return false;
+ } catch (e) {}
+ return true;
+}
+function defaultCompare(x, y) {
+ const isXNaN = NumberIsNaN(x);
+ const isYNaN = NumberIsNaN(y);
+ if (isXNaN && isYNaN) {
+ return 0;
+ }
+ if (isXNaN) {
+ return 1;
+ }
+ if (isYNaN) {
+ return -1;
+ }
+ if (x < y) {
+ return -1;
+ }
+ if (x > y) {
+ return 1;
+ }
+ if (x === 0 && y === 0) {
+ const isXPlusZero = ObjectIs(x, 0);
+ const isYPlusZero = ObjectIs(y, 0);
+ if (!isXPlusZero && isYPlusZero) {
+ return -1;
+ }
+ if (isXPlusZero && !isYPlusZero) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+const BYTES_PER_ELEMENT = 2;
+const float16bitsArrays = new NativeWeakMap();
+function isFloat16Array(target) {
+ return WeakMapPrototypeHas(float16bitsArrays, target) ||
+ !ArrayBufferIsView(target) && hasFloat16ArrayBrand(target);
+}
+function assertFloat16Array(target) {
+ if (!isFloat16Array(target)) {
+ throw NativeTypeError(THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT);
+ }
+}
+function assertSpeciesTypedArray(target, count) {
+ const isTargetFloat16Array = isFloat16Array(target);
+ const isTargetTypedArray = isNativeTypedArray(target);
+ if (!isTargetFloat16Array && !isTargetTypedArray) {
+ throw NativeTypeError(SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT);
+ }
+ if (typeof count === "number") {
+ let length;
+ if (isTargetFloat16Array) {
+ const float16bitsArray = getFloat16BitsArray(target);
+ length = TypedArrayPrototypeGetLength(float16bitsArray);
+ } else {
+ length = TypedArrayPrototypeGetLength(target);
+ }
+ if (length < count) {
+ throw NativeTypeError(
+ DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH);
+
+ }
+ }
+ if (isNativeBigIntTypedArray(target)) {
+ throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES);
+ }
+}
+function getFloat16BitsArray(float16) {
+ const float16bitsArray = WeakMapPrototypeGet(float16bitsArrays, float16);
+ if (float16bitsArray !== undefined) {
+ const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);
+ if (IsDetachedBuffer(buffer)) {
+ throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);
+ }
+ return float16bitsArray;
+ }
+ const buffer = float16.buffer;
+ if (IsDetachedBuffer(buffer)) {
+ throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);
+ }
+ const cloned = ReflectConstruct(Float16Array, [
+ buffer,
+ float16.byteOffset,
+ float16.length],
+ float16.constructor);
+ return WeakMapPrototypeGet(float16bitsArrays, cloned);
+}
+function copyToArray(float16bitsArray) {
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const array = [];
+ for (let i = 0; i < length; ++i) {
+ array[i] = convertToNumber(float16bitsArray[i]);
+ }
+ return array;
+}
+const TypedArrayPrototypeGetters = new NativeWeakSet();
+for (const key of ReflectOwnKeys(TypedArrayPrototype)) {
+ if (key === SymbolToStringTag) {
+ continue;
+ }
+ const descriptor = ReflectGetOwnPropertyDescriptor(TypedArrayPrototype, key);
+ if (ObjectHasOwn(descriptor, "get") && typeof descriptor.get === "function") {
+ WeakSetPrototypeAdd(TypedArrayPrototypeGetters, descriptor.get);
+ }
+}
+const handler = ObjectFreeze({
+ get(target, key, receiver) {
+ if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {
+ return convertToNumber(ReflectGet(target, key));
+ }
+ if (WeakSetPrototypeHas(TypedArrayPrototypeGetters, ObjectPrototype__lookupGetter__(target, key))) {
+ return ReflectGet(target, key);
+ }
+ return ReflectGet(target, key, receiver);
+ },
+ set(target, key, value, receiver) {
+ if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {
+ return ReflectSet(target, key, roundToFloat16Bits(value));
+ }
+ return ReflectSet(target, key, value, receiver);
+ },
+ getOwnPropertyDescriptor(target, key) {
+ if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {
+ const descriptor = ReflectGetOwnPropertyDescriptor(target, key);
+ descriptor.value = convertToNumber(descriptor.value);
+ return descriptor;
+ }
+ return ReflectGetOwnPropertyDescriptor(target, key);
+ },
+ defineProperty(target, key, descriptor) {
+ if (
+ isCanonicalIntegerIndexString(key) &&
+ ObjectHasOwn(target, key) &&
+ ObjectHasOwn(descriptor, "value"))
+ {
+ descriptor.value = roundToFloat16Bits(descriptor.value);
+ return ReflectDefineProperty(target, key, descriptor);
+ }
+ return ReflectDefineProperty(target, key, descriptor);
+ }
+});
+class Float16Array {
+ constructor(input, _byteOffset, _length) {
+ let float16bitsArray;
+ if (isFloat16Array(input)) {
+ float16bitsArray = ReflectConstruct(NativeUint16Array, [getFloat16BitsArray(input)], new.target);
+ } else if (isObject(input) && !isArrayBuffer(input)) {
+ let list;
+ let length;
+ if (isNativeTypedArray(input)) {
+ list = input;
+ length = TypedArrayPrototypeGetLength(input);
+ const buffer = TypedArrayPrototypeGetBuffer(input);
+ const BufferConstructor = !isSharedArrayBuffer(buffer) ?
+ SpeciesConstructor(
+ buffer,
+ NativeArrayBuffer) :
+
+ NativeArrayBuffer;
+ if (IsDetachedBuffer(buffer)) {
+ throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);
+ }
+ if (isNativeBigIntTypedArray(input)) {
+ throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES);
+ }
+ const data = new BufferConstructor(
+ length * BYTES_PER_ELEMENT);
+
+ float16bitsArray = ReflectConstruct(NativeUint16Array, [data], new.target);
+ } else {
+ const iterator = input[SymbolIterator];
+ if (iterator != null && typeof iterator !== "function") {
+ throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE);
+ }
+ if (iterator != null) {
+ if (isOrdinaryArray(input)) {
+ list = input;
+ length = input.length;
+ } else {
+ list = [...input];
+ length = list.length;
+ }
+ } else {
+ list = input;
+ length = ToLength(list.length);
+ }
+ float16bitsArray = ReflectConstruct(NativeUint16Array, [length], new.target);
+ }
+ for (let i = 0; i < length; ++i) {
+ float16bitsArray[i] = roundToFloat16Bits(list[i]);
+ }
+ } else {
+ float16bitsArray = ReflectConstruct(NativeUint16Array, arguments, new.target);
+ }
+ const proxy = new NativeProxy(float16bitsArray, handler);
+ WeakMapPrototypeSet(float16bitsArrays, proxy, float16bitsArray);
+ return proxy;
+ }
+ static from(src, ...opts) {
+ const Constructor = this;
+ if (!ReflectHas(Constructor, brand)) {
+ throw NativeTypeError(
+ THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY);
+
+ }
+ if (Constructor === Float16Array) {
+ if (isFloat16Array(src) && opts.length === 0) {
+ const float16bitsArray = getFloat16BitsArray(src);
+ const uint16 = new NativeUint16Array(
+ TypedArrayPrototypeGetBuffer(float16bitsArray),
+ TypedArrayPrototypeGetByteOffset(float16bitsArray),
+ TypedArrayPrototypeGetLength(float16bitsArray));
+
+ return new Float16Array(
+ TypedArrayPrototypeGetBuffer(TypedArrayPrototypeSlice(uint16)));
+
+ }
+ if (opts.length === 0) {
+ return new Float16Array(
+ TypedArrayPrototypeGetBuffer(
+ Uint16ArrayFrom(src, roundToFloat16Bits)));
+
+
+ }
+ const mapFunc = opts[0];
+ const thisArg = opts[1];
+ return new Float16Array(
+ TypedArrayPrototypeGetBuffer(
+ Uint16ArrayFrom(src, function (val, ...args) {
+ return roundToFloat16Bits(
+ ReflectApply(mapFunc, this, [val, ...safeIfNeeded(args)]));
+
+ }, thisArg)));
+
+
+ }
+ let list;
+ let length;
+ const iterator = src[SymbolIterator];
+ if (iterator != null && typeof iterator !== "function") {
+ throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE);
+ }
+ if (iterator != null) {
+ if (isOrdinaryArray(src)) {
+ list = src;
+ length = src.length;
+ } else if (isOrdinaryNativeTypedArray(src)) {
+ list = src;
+ length = TypedArrayPrototypeGetLength(src);
+ } else {
+ list = [...src];
+ length = list.length;
+ }
+ } else {
+ if (src == null) {
+ throw NativeTypeError(
+ CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT);
+
+ }
+ list = NativeObject(src);
+ length = ToLength(list.length);
+ }
+ const array = new Constructor(length);
+ if (opts.length === 0) {
+ for (let i = 0; i < length; ++i) {
+ array[i] = list[i];
+ }
+ } else {
+ const mapFunc = opts[0];
+ const thisArg = opts[1];
+ for (let i = 0; i < length; ++i) {
+ array[i] = ReflectApply(mapFunc, thisArg, [list[i], i]);
+ }
+ }
+ return array;
+ }
+ static of(...items) {
+ const Constructor = this;
+ if (!ReflectHas(Constructor, brand)) {
+ throw NativeTypeError(
+ THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY);
+
+ }
+ const length = items.length;
+ if (Constructor === Float16Array) {
+ const proxy = new Float16Array(length);
+ const float16bitsArray = getFloat16BitsArray(proxy);
+ for (let i = 0; i < length; ++i) {
+ float16bitsArray[i] = roundToFloat16Bits(items[i]);
+ }
+ return proxy;
+ }
+ const array = new Constructor(length);
+ for (let i = 0; i < length; ++i) {
+ array[i] = items[i];
+ }
+ return array;
+ }
+ keys() {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ return TypedArrayPrototypeKeys(float16bitsArray);
+ }
+ values() {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ return wrap(function* () {
+ for (const val of TypedArrayPrototypeValues(float16bitsArray)) {
+ yield convertToNumber(val);
+ }
+ }());
+ }
+ entries() {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ return wrap(function* () {
+ for (const [i, val] of TypedArrayPrototypeEntries(float16bitsArray)) {
+ yield [i, convertToNumber(val)];
+ }
+ }());
+ }
+ at(index) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const relativeIndex = ToIntegerOrInfinity(index);
+ const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex;
+ if (k < 0 || k >= length) {
+ return;
+ }
+ return convertToNumber(float16bitsArray[k]);
+ }
+ map(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);
+ if (Constructor === Float16Array) {
+ const proxy = new Float16Array(length);
+ const array = getFloat16BitsArray(proxy);
+ for (let i = 0; i < length; ++i) {
+ const val = convertToNumber(float16bitsArray[i]);
+ array[i] = roundToFloat16Bits(
+ ReflectApply(callback, thisArg, [val, i, this]));
+
+ }
+ return proxy;
+ }
+ const array = new Constructor(length);
+ assertSpeciesTypedArray(array, length);
+ for (let i = 0; i < length; ++i) {
+ const val = convertToNumber(float16bitsArray[i]);
+ array[i] = ReflectApply(callback, thisArg, [val, i, this]);
+ }
+ return array;
+ }
+ filter(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ const kept = [];
+ for (let i = 0; i < length; ++i) {
+ const val = convertToNumber(float16bitsArray[i]);
+ if (ReflectApply(callback, thisArg, [val, i, this])) {
+ ArrayPrototypePush(kept, val);
+ }
+ }
+ const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);
+ const array = new Constructor(kept);
+ assertSpeciesTypedArray(array);
+ return array;
+ }
+ reduce(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ if (length === 0 && opts.length === 0) {
+ throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE);
+ }
+ let accumulator, start;
+ if (opts.length === 0) {
+ accumulator = convertToNumber(float16bitsArray[0]);
+ start = 1;
+ } else {
+ accumulator = opts[0];
+ start = 0;
+ }
+ for (let i = start; i < length; ++i) {
+ accumulator = callback(
+ accumulator,
+ convertToNumber(float16bitsArray[i]),
+ i,
+ this);
+
+ }
+ return accumulator;
+ }
+ reduceRight(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ if (length === 0 && opts.length === 0) {
+ throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE);
+ }
+ let accumulator, start;
+ if (opts.length === 0) {
+ accumulator = convertToNumber(float16bitsArray[length - 1]);
+ start = length - 2;
+ } else {
+ accumulator = opts[0];
+ start = length - 1;
+ }
+ for (let i = start; i >= 0; --i) {
+ accumulator = callback(
+ accumulator,
+ convertToNumber(float16bitsArray[i]),
+ i,
+ this);
+
+ }
+ return accumulator;
+ }
+ forEach(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = 0; i < length; ++i) {
+ ReflectApply(callback, thisArg, [
+ convertToNumber(float16bitsArray[i]),
+ i,
+ this]);
+
+ }
+ }
+ find(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = 0; i < length; ++i) {
+ const value = convertToNumber(float16bitsArray[i]);
+ if (ReflectApply(callback, thisArg, [value, i, this])) {
+ return value;
+ }
+ }
+ }
+ findIndex(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = 0; i < length; ++i) {
+ const value = convertToNumber(float16bitsArray[i]);
+ if (ReflectApply(callback, thisArg, [value, i, this])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ findLast(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = length - 1; i >= 0; --i) {
+ const value = convertToNumber(float16bitsArray[i]);
+ if (ReflectApply(callback, thisArg, [value, i, this])) {
+ return value;
+ }
+ }
+ }
+ findLastIndex(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = length - 1; i >= 0; --i) {
+ const value = convertToNumber(float16bitsArray[i]);
+ if (ReflectApply(callback, thisArg, [value, i, this])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ every(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = 0; i < length; ++i) {
+ if (
+ !ReflectApply(callback, thisArg, [
+ convertToNumber(float16bitsArray[i]),
+ i,
+ this]))
+
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ some(callback, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const thisArg = opts[0];
+ for (let i = 0; i < length; ++i) {
+ if (
+ ReflectApply(callback, thisArg, [
+ convertToNumber(float16bitsArray[i]),
+ i,
+ this]))
+
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ set(input, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const targetOffset = ToIntegerOrInfinity(opts[0]);
+ if (targetOffset < 0) {
+ throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);
+ }
+ if (input == null) {
+ throw NativeTypeError(
+ CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT);
+
+ }
+ if (isNativeBigIntTypedArray(input)) {
+ throw NativeTypeError(
+ CANNOT_MIX_BIGINT_AND_OTHER_TYPES);
+
+ }
+ if (isFloat16Array(input)) {
+ return TypedArrayPrototypeSet(
+ getFloat16BitsArray(this),
+ getFloat16BitsArray(input),
+ targetOffset);
+
+ }
+ if (isNativeTypedArray(input)) {
+ const buffer = TypedArrayPrototypeGetBuffer(input);
+ if (IsDetachedBuffer(buffer)) {
+ throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);
+ }
+ }
+ const targetLength = TypedArrayPrototypeGetLength(float16bitsArray);
+ const src = NativeObject(input);
+ const srcLength = ToLength(src.length);
+ if (targetOffset === Infinity || srcLength + targetOffset > targetLength) {
+ throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);
+ }
+ for (let i = 0; i < srcLength; ++i) {
+ float16bitsArray[i + targetOffset] = roundToFloat16Bits(src[i]);
+ }
+ }
+ reverse() {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ TypedArrayPrototypeReverse(float16bitsArray);
+ return this;
+ }
+ fill(value, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ TypedArrayPrototypeFill(
+ float16bitsArray,
+ roundToFloat16Bits(value),
+ ...safeIfNeeded(opts));
+
+ return this;
+ }
+ copyWithin(target, start, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ TypedArrayPrototypeCopyWithin(float16bitsArray, target, start, ...safeIfNeeded(opts));
+ return this;
+ }
+ sort(compareFn) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const sortCompare = compareFn !== undefined ? compareFn : defaultCompare;
+ TypedArrayPrototypeSort(float16bitsArray, (x, y) => {
+ return sortCompare(convertToNumber(x), convertToNumber(y));
+ });
+ return this;
+ }
+ slice(start, end) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);
+ if (Constructor === Float16Array) {
+ const uint16 = new NativeUint16Array(
+ TypedArrayPrototypeGetBuffer(float16bitsArray),
+ TypedArrayPrototypeGetByteOffset(float16bitsArray),
+ TypedArrayPrototypeGetLength(float16bitsArray));
+
+ return new Float16Array(
+ TypedArrayPrototypeGetBuffer(
+ TypedArrayPrototypeSlice(uint16, start, end)));
+
+
+ }
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ const relativeStart = ToIntegerOrInfinity(start);
+ const relativeEnd = end === undefined ? length : ToIntegerOrInfinity(end);
+ let k;
+ if (relativeStart === -Infinity) {
+ k = 0;
+ } else if (relativeStart < 0) {
+ k = length + relativeStart > 0 ? length + relativeStart : 0;
+ } else {
+ k = length < relativeStart ? length : relativeStart;
+ }
+ let final;
+ if (relativeEnd === -Infinity) {
+ final = 0;
+ } else if (relativeEnd < 0) {
+ final = length + relativeEnd > 0 ? length + relativeEnd : 0;
+ } else {
+ final = length < relativeEnd ? length : relativeEnd;
+ }
+ const count = final - k > 0 ? final - k : 0;
+ const array = new Constructor(count);
+ assertSpeciesTypedArray(array, count);
+ if (count === 0) {
+ return array;
+ }
+ const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);
+ if (IsDetachedBuffer(buffer)) {
+ throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);
+ }
+ let n = 0;
+ while (k < final) {
+ array[n] = convertToNumber(float16bitsArray[k]);
+ ++k;
+ ++n;
+ }
+ return array;
+ }
+ subarray(begin, end) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);
+ const uint16 = new NativeUint16Array(
+ TypedArrayPrototypeGetBuffer(float16bitsArray),
+ TypedArrayPrototypeGetByteOffset(float16bitsArray),
+ TypedArrayPrototypeGetLength(float16bitsArray));
+
+ const uint16Subarray = TypedArrayPrototypeSubarray(uint16, begin, end);
+ const array = new Constructor(
+ TypedArrayPrototypeGetBuffer(uint16Subarray),
+ TypedArrayPrototypeGetByteOffset(uint16Subarray),
+ TypedArrayPrototypeGetLength(uint16Subarray));
+
+ assertSpeciesTypedArray(array);
+ return array;
+ }
+ indexOf(element, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ let from = ToIntegerOrInfinity(opts[0]);
+ if (from === Infinity) {
+ return -1;
+ }
+ if (from < 0) {
+ from += length;
+ if (from < 0) {
+ from = 0;
+ }
+ }
+ for (let i = from; i < length; ++i) {
+ if (
+ ObjectHasOwn(float16bitsArray, i) &&
+ convertToNumber(float16bitsArray[i]) === element)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+ lastIndexOf(element, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ let from = opts.length >= 1 ? ToIntegerOrInfinity(opts[0]) : length - 1;
+ if (from === -Infinity) {
+ return -1;
+ }
+ if (from >= 0) {
+ from = from < length - 1 ? from : length - 1;
+ } else {
+ from += length;
+ }
+ for (let i = from; i >= 0; --i) {
+ if (
+ ObjectHasOwn(float16bitsArray, i) &&
+ convertToNumber(float16bitsArray[i]) === element)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+ includes(element, ...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const length = TypedArrayPrototypeGetLength(float16bitsArray);
+ let from = ToIntegerOrInfinity(opts[0]);
+ if (from === Infinity) {
+ return false;
+ }
+ if (from < 0) {
+ from += length;
+ if (from < 0) {
+ from = 0;
+ }
+ }
+ const isNaN = NumberIsNaN(element);
+ for (let i = from; i < length; ++i) {
+ const value = convertToNumber(float16bitsArray[i]);
+ if (isNaN && NumberIsNaN(value)) {
+ return true;
+ }
+ if (value === element) {
+ return true;
+ }
+ }
+ return false;
+ }
+ join(separator) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const array = copyToArray(float16bitsArray);
+ return ArrayPrototypeJoin(array, separator);
+ }
+ toLocaleString(...opts) {
+ assertFloat16Array(this);
+ const float16bitsArray = getFloat16BitsArray(this);
+ const array = copyToArray(float16bitsArray);
+ return ArrayPrototypeToLocaleString(array, ...safeIfNeeded(opts));
+ }
+ get [SymbolToStringTag]() {
+ if (isFloat16Array(this)) {
+ return "Float16Array";
+ }
+ }
+}
+ObjectDefineProperty(Float16Array, "BYTES_PER_ELEMENT", {
+ value: BYTES_PER_ELEMENT
+});
+ObjectDefineProperty(Float16Array, brand, {});
+ReflectSetPrototypeOf(Float16Array, TypedArray);
+const Float16ArrayPrototype = Float16Array.prototype;
+ObjectDefineProperty(Float16ArrayPrototype, "BYTES_PER_ELEMENT", {
+ value: BYTES_PER_ELEMENT
+});
+ObjectDefineProperty(Float16ArrayPrototype, SymbolIterator, {
+ value: Float16ArrayPrototype.values,
+ writable: true,
+ configurable: true
+});
+ReflectSetPrototypeOf(Float16ArrayPrototype, TypedArrayPrototype);
+
+function isTypedArray(target) {
+ return isNativeTypedArray(target) || isFloat16Array(target);
+}
+
+function getFloat16(dataView, byteOffset, ...opts) {
+ return convertToNumber(
+ DataViewPrototypeGetUint16(dataView, byteOffset, ...safeIfNeeded(opts)));
+
+}
+function setFloat16(dataView, byteOffset, value, ...opts) {
+ return DataViewPrototypeSetUint16(
+ dataView,
+ byteOffset,
+ roundToFloat16Bits(value),
+ ...safeIfNeeded(opts));
+
+}
+
+function hfround(x) {
+ const number = +x;
+ if (!NumberIsFinite(number) || number === 0) {
+ return number;
+ }
+ const x16 = roundToFloat16Bits(number);
+ return convertToNumber(x16);
+}
+
+export { Float16Array, getFloat16, hfround, isFloat16Array, isTypedArray, setFloat16 };
+//# sourceMappingURL=float16.js.map \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js.map b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js.map
new file mode 100644
index 0000000000..5996472809
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/external/petamoriken/float16/float16.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"float16.js","names":["THIS_IS_NOT_AN_OBJECT","THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT","THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY","THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT","SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT","DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH","ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER","CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT","CANNOT_MIX_BIGINT_AND_OTHER_TYPES","ITERATOR_PROPERTY_IS_NOT_CALLABLE","REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE","OFFSET_IS_OUT_OF_BOUNDS","uncurryThis","target","thisArg","args","ReflectApply","uncurryThisGetter","key","ReflectGetOwnPropertyDescriptor","get","apply","construct","ReflectConstruct","defineProperty","ReflectDefineProperty","ReflectGet","getOwnPropertyDescriptor","getPrototypeOf","ReflectGetPrototypeOf","has","ReflectHas","ownKeys","ReflectOwnKeys","set","ReflectSet","setPrototypeOf","ReflectSetPrototypeOf","Reflect","NativeProxy","Proxy","MAX_SAFE_INTEGER","isFinite","NumberIsFinite","isNaN","NumberIsNaN","Number","iterator","SymbolIterator","species","SymbolSpecies","toStringTag","SymbolToStringTag","for","SymbolFor","Symbol","NativeObject","Object","create","ObjectCreate","ObjectDefineProperty","freeze","ObjectFreeze","is","ObjectIs","ObjectPrototype","prototype","ObjectPrototype__lookupGetter__","__lookupGetter__","object","NativeTypeError","descriptor","undefined","ObjectHasOwn","hasOwn","hasOwnProperty","NativeArray","Array","ArrayIsArray","isArray","ArrayPrototype","ArrayPrototypeJoin","join","ArrayPrototypePush","push","ArrayPrototypeToLocaleString","toLocaleString","NativeArrayPrototypeSymbolIterator","ArrayPrototypeSymbolIterator","MathTrunc","Math","trunc","NativeArrayBuffer","ArrayBuffer","ArrayBufferIsView","isView","ArrayBufferPrototype","ArrayBufferPrototypeSlice","slice","ArrayBufferPrototypeGetByteLength","NativeSharedArrayBuffer","SharedArrayBuffer","SharedArrayBufferPrototypeGetByteLength","TypedArray","Uint8Array","TypedArrayFrom","from","TypedArrayPrototype","NativeTypedArrayPrototypeSymbolIterator","TypedArrayPrototypeKeys","keys","TypedArrayPrototypeValues","values","TypedArrayPrototypeEntries","entries","TypedArrayPrototypeSet","TypedArrayPrototypeReverse","reverse","TypedArrayPrototypeFill","fill","TypedArrayPrototypeCopyWithin","copyWithin","TypedArrayPrototypeSort","sort","TypedArrayPrototypeSlice","TypedArrayPrototypeSubarray","subarray","TypedArrayPrototypeGetBuffer","TypedArrayPrototypeGetByteOffset","TypedArrayPrototypeGetLength","TypedArrayPrototypeGetSymbolToStringTag","NativeUint16Array","Uint16Array","Uint16ArrayFrom","NativeUint32Array","Uint32Array","NativeFloat32Array","Float32Array","ArrayIteratorPrototype","ArrayIteratorPrototypeNext","next","GeneratorPrototypeNext","IteratorPrototype","DataViewPrototype","DataView","DataViewPrototypeGetUint16","getUint16","DataViewPrototypeSetUint16","setUint16","TypeError","NativeRangeError","RangeError","NativeWeakSet","WeakSet","WeakSetPrototype","WeakSetPrototypeAdd","add","WeakSetPrototypeHas","NativeWeakMap","WeakMap","WeakMapPrototype","WeakMapPrototypeGet","WeakMapPrototypeHas","WeakMapPrototypeSet","arrayIterators","SafeIteratorPrototype","value","arrayIterator","safeIfNeeded","array","safe","generators","DummyArrayIteratorPrototype","generator","writable","configurable","wrap","dummy","isObject","isObjectLike","isNativeTypedArray","isNativeBigIntTypedArray","typedArrayName","isArrayBuffer","e","isSharedArrayBuffer","isOrdinaryArray","isOrdinaryNativeTypedArray","isCanonicalIntegerIndexString","number","brand","hasFloat16ArrayBrand","constructor","buffer","floatView","uint32View","baseTable","shiftTable","i","roundToFloat16Bits","num","f","mantissaTable","exponentTable","offsetTable","m","convertToNumber","float16bits","ToIntegerOrInfinity","ToLength","length","SpeciesConstructor","defaultConstructor","IsDetachedBuffer","defaultCompare","x","y","isXNaN","isYNaN","isXPlusZero","isYPlusZero","BYTES_PER_ELEMENT","float16bitsArrays","isFloat16Array","assertFloat16Array","assertSpeciesTypedArray","count","isTargetFloat16Array","isTargetTypedArray","float16bitsArray","getFloat16BitsArray","float16","cloned","Float16Array","byteOffset","copyToArray","TypedArrayPrototypeGetters","handler","receiver","input","_byteOffset","_length","new","list","BufferConstructor","data","arguments","proxy","src","opts","Constructor","uint16","mapFunc","val","of","items","at","index","relativeIndex","k","map","callback","filter","kept","reduce","accumulator","start","reduceRight","forEach","find","findIndex","findLast","findLastIndex","every","some","targetOffset","targetLength","srcLength","Infinity","compareFn","sortCompare","end","relativeStart","relativeEnd","final","n","begin","uint16Subarray","indexOf","element","lastIndexOf","includes","separator","Float16ArrayPrototype","isTypedArray","getFloat16","dataView","setFloat16","hfround","x16"],"sources":["../../../../src/external/petamoriken/float16/float16.js"],"sourcesContent":["/*! @petamoriken/float16 v3.6.6 | MIT License - https://github.com/petamoriken/float16 */\n\nconst THIS_IS_NOT_AN_OBJECT = \"This is not an object\";\nconst THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT = \"This is not a Float16Array object\";\nconst THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY =\n \"This constructor is not a subclass of Float16Array\";\nconst THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT =\n \"The constructor property value is not an object\";\nconst SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT =\n \"Species constructor didn't return TypedArray object\";\nconst DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH =\n \"Derived constructor created TypedArray object which was too small length\";\nconst ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER =\n \"Attempting to access detached ArrayBuffer\";\nconst CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT =\n \"Cannot convert undefined or null to object\";\nconst CANNOT_MIX_BIGINT_AND_OTHER_TYPES =\n \"Cannot mix BigInt and other types, use explicit conversions\";\nconst ITERATOR_PROPERTY_IS_NOT_CALLABLE = \"@@iterator property is not callable\";\nconst REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE =\n \"Reduce of empty array with no initial value\";\nconst OFFSET_IS_OUT_OF_BOUNDS = \"Offset is out of bounds\";\n\nfunction uncurryThis(target) {\n return (thisArg, ...args) => {\n return ReflectApply(target, thisArg, args);\n };\n}\nfunction uncurryThisGetter(target, key) {\n return uncurryThis(\n ReflectGetOwnPropertyDescriptor(\n target,\n key\n ).get\n );\n}\nconst {\n apply: ReflectApply,\n construct: ReflectConstruct,\n defineProperty: ReflectDefineProperty,\n get: ReflectGet,\n getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,\n getPrototypeOf: ReflectGetPrototypeOf,\n has: ReflectHas,\n ownKeys: ReflectOwnKeys,\n set: ReflectSet,\n setPrototypeOf: ReflectSetPrototypeOf,\n} = Reflect;\nconst NativeProxy = Proxy;\nconst {\n MAX_SAFE_INTEGER: MAX_SAFE_INTEGER,\n isFinite: NumberIsFinite,\n isNaN: NumberIsNaN,\n} = Number;\nconst {\n iterator: SymbolIterator,\n species: SymbolSpecies,\n toStringTag: SymbolToStringTag,\n for: SymbolFor,\n} = Symbol;\nconst NativeObject = Object;\nconst {\n create: ObjectCreate,\n defineProperty: ObjectDefineProperty,\n freeze: ObjectFreeze,\n is: ObjectIs,\n} = NativeObject;\nconst ObjectPrototype = NativeObject.prototype;\nconst ObjectPrototype__lookupGetter__ = (ObjectPrototype).__lookupGetter__\n ? uncurryThis( (ObjectPrototype).__lookupGetter__)\n : (object, key) => {\n if (object == null) {\n throw NativeTypeError(\n CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT\n );\n }\n let target = NativeObject(object);\n do {\n const descriptor = ReflectGetOwnPropertyDescriptor(target, key);\n if (descriptor !== undefined) {\n if (ObjectHasOwn(descriptor, \"get\")) {\n return descriptor.get;\n }\n return;\n }\n } while ((target = ReflectGetPrototypeOf(target)) !== null);\n };\nconst ObjectHasOwn = (NativeObject).hasOwn ||\n uncurryThis(ObjectPrototype.hasOwnProperty);\nconst NativeArray = Array;\nconst ArrayIsArray = NativeArray.isArray;\nconst ArrayPrototype = NativeArray.prototype;\nconst ArrayPrototypeJoin = uncurryThis(ArrayPrototype.join);\nconst ArrayPrototypePush = uncurryThis(ArrayPrototype.push);\nconst ArrayPrototypeToLocaleString = uncurryThis(\n ArrayPrototype.toLocaleString\n);\nconst NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator];\nconst ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator);\nconst MathTrunc = Math.trunc;\nconst NativeArrayBuffer = ArrayBuffer;\nconst ArrayBufferIsView = NativeArrayBuffer.isView;\nconst ArrayBufferPrototype = NativeArrayBuffer.prototype;\nconst ArrayBufferPrototypeSlice = uncurryThis(ArrayBufferPrototype.slice);\nconst ArrayBufferPrototypeGetByteLength = uncurryThisGetter(ArrayBufferPrototype, \"byteLength\");\nconst NativeSharedArrayBuffer = typeof SharedArrayBuffer !== \"undefined\" ? SharedArrayBuffer : null;\nconst SharedArrayBufferPrototypeGetByteLength = NativeSharedArrayBuffer\n && uncurryThisGetter(NativeSharedArrayBuffer.prototype, \"byteLength\");\nconst TypedArray = ReflectGetPrototypeOf(Uint8Array);\nconst TypedArrayFrom = TypedArray.from;\nconst TypedArrayPrototype = TypedArray.prototype;\nconst NativeTypedArrayPrototypeSymbolIterator = TypedArrayPrototype[SymbolIterator];\nconst TypedArrayPrototypeKeys = uncurryThis(TypedArrayPrototype.keys);\nconst TypedArrayPrototypeValues = uncurryThis(\n TypedArrayPrototype.values\n);\nconst TypedArrayPrototypeEntries = uncurryThis(\n TypedArrayPrototype.entries\n);\nconst TypedArrayPrototypeSet = uncurryThis(TypedArrayPrototype.set);\nconst TypedArrayPrototypeReverse = uncurryThis(\n TypedArrayPrototype.reverse\n);\nconst TypedArrayPrototypeFill = uncurryThis(TypedArrayPrototype.fill);\nconst TypedArrayPrototypeCopyWithin = uncurryThis(\n TypedArrayPrototype.copyWithin\n);\nconst TypedArrayPrototypeSort = uncurryThis(TypedArrayPrototype.sort);\nconst TypedArrayPrototypeSlice = uncurryThis(TypedArrayPrototype.slice);\nconst TypedArrayPrototypeSubarray = uncurryThis(\n TypedArrayPrototype.subarray\n);\nconst TypedArrayPrototypeGetBuffer = uncurryThisGetter(\n TypedArrayPrototype,\n \"buffer\"\n);\nconst TypedArrayPrototypeGetByteOffset = uncurryThisGetter(\n TypedArrayPrototype,\n \"byteOffset\"\n);\nconst TypedArrayPrototypeGetLength = uncurryThisGetter(\n TypedArrayPrototype,\n \"length\"\n);\nconst TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter(\n TypedArrayPrototype,\n SymbolToStringTag\n);\nconst NativeUint16Array = Uint16Array;\nconst Uint16ArrayFrom = (...args) => {\n return ReflectApply(TypedArrayFrom, NativeUint16Array, args);\n};\nconst NativeUint32Array = Uint32Array;\nconst NativeFloat32Array = Float32Array;\nconst ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]());\nconst ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next);\nconst GeneratorPrototypeNext = uncurryThis((function* () {})().next);\nconst IteratorPrototype = ReflectGetPrototypeOf(ArrayIteratorPrototype);\nconst DataViewPrototype = DataView.prototype;\nconst DataViewPrototypeGetUint16 = uncurryThis(\n DataViewPrototype.getUint16\n);\nconst DataViewPrototypeSetUint16 = uncurryThis(\n DataViewPrototype.setUint16\n);\nconst NativeTypeError = TypeError;\nconst NativeRangeError = RangeError;\nconst NativeWeakSet = WeakSet;\nconst WeakSetPrototype = NativeWeakSet.prototype;\nconst WeakSetPrototypeAdd = uncurryThis(WeakSetPrototype.add);\nconst WeakSetPrototypeHas = uncurryThis(WeakSetPrototype.has);\nconst NativeWeakMap = WeakMap;\nconst WeakMapPrototype = NativeWeakMap.prototype;\nconst WeakMapPrototypeGet = uncurryThis(WeakMapPrototype.get);\nconst WeakMapPrototypeHas = uncurryThis(WeakMapPrototype.has);\nconst WeakMapPrototypeSet = uncurryThis(WeakMapPrototype.set);\n\nconst arrayIterators = new NativeWeakMap();\nconst SafeIteratorPrototype = ObjectCreate(null, {\n next: {\n value: function next() {\n const arrayIterator = WeakMapPrototypeGet(arrayIterators, this);\n return ArrayIteratorPrototypeNext(arrayIterator);\n },\n },\n [SymbolIterator]: {\n value: function values() {\n return this;\n },\n },\n});\nfunction safeIfNeeded(array) {\n if (array[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {\n return array;\n }\n const safe = ObjectCreate(SafeIteratorPrototype);\n WeakMapPrototypeSet(arrayIterators, safe, ArrayPrototypeSymbolIterator(array));\n return safe;\n}\nconst generators = new NativeWeakMap();\nconst DummyArrayIteratorPrototype = ObjectCreate(IteratorPrototype, {\n next: {\n value: function next() {\n const generator = WeakMapPrototypeGet(generators, this);\n return GeneratorPrototypeNext(generator);\n },\n writable: true,\n configurable: true,\n },\n});\nfor (const key of ReflectOwnKeys(ArrayIteratorPrototype)) {\n if (key === \"next\") {\n continue;\n }\n ObjectDefineProperty(DummyArrayIteratorPrototype, key, ReflectGetOwnPropertyDescriptor(ArrayIteratorPrototype, key));\n}\nfunction wrap(generator) {\n const dummy = ObjectCreate(DummyArrayIteratorPrototype);\n WeakMapPrototypeSet(generators, dummy, generator);\n return dummy;\n}\n\nfunction isObject(value) {\n return (value !== null && typeof value === \"object\") ||\n typeof value === \"function\";\n}\nfunction isObjectLike(value) {\n return value !== null && typeof value === \"object\";\n}\nfunction isNativeTypedArray(value) {\n return TypedArrayPrototypeGetSymbolToStringTag(value) !== undefined;\n}\nfunction isNativeBigIntTypedArray(value) {\n const typedArrayName = TypedArrayPrototypeGetSymbolToStringTag(value);\n return typedArrayName === \"BigInt64Array\" ||\n typedArrayName === \"BigUint64Array\";\n}\nfunction isArrayBuffer(value) {\n try {\n ArrayBufferPrototypeGetByteLength( (value));\n return true;\n } catch (e) {\n return false;\n }\n}\nfunction isSharedArrayBuffer(value) {\n if (NativeSharedArrayBuffer === null) {\n return false;\n }\n try {\n SharedArrayBufferPrototypeGetByteLength( (value));\n return true;\n } catch (e) {\n return false;\n }\n}\nfunction isOrdinaryArray(value) {\n if (!ArrayIsArray(value)) {\n return false;\n }\n if (value[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {\n return true;\n }\n const iterator = value[SymbolIterator]();\n return iterator[SymbolToStringTag] === \"Array Iterator\";\n}\nfunction isOrdinaryNativeTypedArray(value) {\n if (!isNativeTypedArray(value)) {\n return false;\n }\n if (value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator) {\n return true;\n }\n const iterator = value[SymbolIterator]();\n return iterator[SymbolToStringTag] === \"Array Iterator\";\n}\nfunction isCanonicalIntegerIndexString(value) {\n if (typeof value !== \"string\") {\n return false;\n }\n const number = +value;\n if (value !== number + \"\") {\n return false;\n }\n if (!NumberIsFinite(number)) {\n return false;\n }\n return number === MathTrunc(number);\n}\n\nconst brand = SymbolFor(\"__Float16Array__\");\nfunction hasFloat16ArrayBrand(target) {\n if (!isObjectLike(target)) {\n return false;\n }\n const prototype = ReflectGetPrototypeOf(target);\n if (!isObjectLike(prototype)) {\n return false;\n }\n const constructor = prototype.constructor;\n if (constructor === undefined) {\n return false;\n }\n if (!isObject(constructor)) {\n throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT);\n }\n return ReflectHas(constructor, brand);\n}\n\nconst buffer = new NativeArrayBuffer(4);\nconst floatView = new NativeFloat32Array(buffer);\nconst uint32View = new NativeUint32Array(buffer);\nconst baseTable = new NativeUint32Array(512);\nconst shiftTable = new NativeUint32Array(512);\nfor (let i = 0; i < 256; ++i) {\n const e = i - 127;\n if (e < -27) {\n baseTable[i] = 0x0000;\n baseTable[i | 0x100] = 0x8000;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n } else if (e < -14) {\n baseTable[i] = 0x0400 >> (-e - 14);\n baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;\n shiftTable[i] = -e - 1;\n shiftTable[i | 0x100] = -e - 1;\n } else if (e <= 15) {\n baseTable[i] = (e + 15) << 10;\n baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n } else if (e < 128) {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 24;\n shiftTable[i | 0x100] = 24;\n } else {\n baseTable[i] = 0x7c00;\n baseTable[i | 0x100] = 0xfc00;\n shiftTable[i] = 13;\n shiftTable[i | 0x100] = 13;\n }\n}\nfunction roundToFloat16Bits(num) {\n floatView[0] = (num);\n const f = uint32View[0];\n const e = (f >> 23) & 0x1ff;\n return baseTable[e] + ((f & 0x007fffff) >> shiftTable[e]);\n}\nconst mantissaTable = new NativeUint32Array(2048);\nconst exponentTable = new NativeUint32Array(64);\nconst offsetTable = new NativeUint32Array(64);\nfor (let i = 1; i < 1024; ++i) {\n let m = i << 13;\n let e = 0;\n while((m & 0x00800000) === 0) {\n m <<= 1;\n e -= 0x00800000;\n }\n m &= ~0x00800000;\n e += 0x38800000;\n mantissaTable[i] = m | e;\n}\nfor (let i = 1024; i < 2048; ++i) {\n mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);\n}\nfor (let i = 1; i < 31; ++i) {\n exponentTable[i] = i << 23;\n}\nexponentTable[31] = 0x47800000;\nexponentTable[32] = 0x80000000;\nfor (let i = 33; i < 63; ++i) {\n exponentTable[i] = 0x80000000 + ((i - 32) << 23);\n}\nexponentTable[63] = 0xc7800000;\nfor (let i = 1; i < 64; ++i) {\n if (i !== 32) {\n offsetTable[i] = 1024;\n }\n}\nfunction convertToNumber(float16bits) {\n const m = float16bits >> 10;\n uint32View[0] = mantissaTable[offsetTable[m] + (float16bits & 0x3ff)] + exponentTable[m];\n return floatView[0];\n}\n\nfunction ToIntegerOrInfinity(target) {\n const number = +target;\n if (NumberIsNaN(number) || number === 0) {\n return 0;\n }\n return MathTrunc(number);\n}\nfunction ToLength(target) {\n const length = ToIntegerOrInfinity(target);\n if (length < 0) {\n return 0;\n }\n return length < MAX_SAFE_INTEGER\n ? length\n : MAX_SAFE_INTEGER;\n}\nfunction SpeciesConstructor(target, defaultConstructor) {\n if (!isObject(target)) {\n throw NativeTypeError(THIS_IS_NOT_AN_OBJECT);\n }\n const constructor = target.constructor;\n if (constructor === undefined) {\n return defaultConstructor;\n }\n if (!isObject(constructor)) {\n throw NativeTypeError(THE_CONSTRUCTOR_PROPERTY_VALUE_IS_NOT_AN_OBJECT);\n }\n const species = constructor[SymbolSpecies];\n if (species == null) {\n return defaultConstructor;\n }\n return species;\n}\nfunction IsDetachedBuffer(buffer) {\n if (isSharedArrayBuffer(buffer)) {\n return false;\n }\n try {\n ArrayBufferPrototypeSlice(buffer, 0, 0);\n return false;\n } catch (e) {}\n return true;\n}\nfunction defaultCompare(x, y) {\n const isXNaN = NumberIsNaN(x);\n const isYNaN = NumberIsNaN(y);\n if (isXNaN && isYNaN) {\n return 0;\n }\n if (isXNaN) {\n return 1;\n }\n if (isYNaN) {\n return -1;\n }\n if (x < y) {\n return -1;\n }\n if (x > y) {\n return 1;\n }\n if (x === 0 && y === 0) {\n const isXPlusZero = ObjectIs(x, 0);\n const isYPlusZero = ObjectIs(y, 0);\n if (!isXPlusZero && isYPlusZero) {\n return -1;\n }\n if (isXPlusZero && !isYPlusZero) {\n return 1;\n }\n }\n return 0;\n}\n\nconst BYTES_PER_ELEMENT = 2;\nconst float16bitsArrays = new NativeWeakMap();\nfunction isFloat16Array(target) {\n return WeakMapPrototypeHas(float16bitsArrays, target) ||\n (!ArrayBufferIsView(target) && hasFloat16ArrayBrand(target));\n}\nfunction assertFloat16Array(target) {\n if (!isFloat16Array(target)) {\n throw NativeTypeError(THIS_IS_NOT_A_FLOAT16ARRAY_OBJECT);\n }\n}\nfunction assertSpeciesTypedArray(target, count) {\n const isTargetFloat16Array = isFloat16Array(target);\n const isTargetTypedArray = isNativeTypedArray(target);\n if (!isTargetFloat16Array && !isTargetTypedArray) {\n throw NativeTypeError(SPECIES_CONSTRUCTOR_DIDNT_RETURN_TYPEDARRAY_OBJECT);\n }\n if (typeof count === \"number\") {\n let length;\n if (isTargetFloat16Array) {\n const float16bitsArray = getFloat16BitsArray(target);\n length = TypedArrayPrototypeGetLength(float16bitsArray);\n } else {\n length = TypedArrayPrototypeGetLength(target);\n }\n if (length < count) {\n throw NativeTypeError(\n DERIVED_CONSTRUCTOR_CREATED_TYPEDARRAY_OBJECT_WHICH_WAS_TOO_SMALL_LENGTH\n );\n }\n }\n if (isNativeBigIntTypedArray(target)) {\n throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES);\n }\n}\nfunction getFloat16BitsArray(float16) {\n const float16bitsArray = WeakMapPrototypeGet(float16bitsArrays, float16);\n if (float16bitsArray !== undefined) {\n const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);\n if (IsDetachedBuffer(buffer)) {\n throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);\n }\n return float16bitsArray;\n }\n const buffer = (float16).buffer;\n if (IsDetachedBuffer(buffer)) {\n throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);\n }\n const cloned = ReflectConstruct(Float16Array, [\n buffer,\n (float16).byteOffset,\n (float16).length,\n ], float16.constructor);\n return WeakMapPrototypeGet(float16bitsArrays, cloned);\n}\nfunction copyToArray(float16bitsArray) {\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const array = [];\n for (let i = 0; i < length; ++i) {\n array[i] = convertToNumber(float16bitsArray[i]);\n }\n return array;\n}\nconst TypedArrayPrototypeGetters = new NativeWeakSet();\nfor (const key of ReflectOwnKeys(TypedArrayPrototype)) {\n if (key === SymbolToStringTag) {\n continue;\n }\n const descriptor = ReflectGetOwnPropertyDescriptor(TypedArrayPrototype, key);\n if (ObjectHasOwn(descriptor, \"get\") && typeof descriptor.get === \"function\") {\n WeakSetPrototypeAdd(TypedArrayPrototypeGetters, descriptor.get);\n }\n}\nconst handler = ObjectFreeze( ({\n get(target, key, receiver) {\n if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {\n return convertToNumber(ReflectGet(target, key));\n }\n if (WeakSetPrototypeHas(TypedArrayPrototypeGetters, ObjectPrototype__lookupGetter__(target, key))) {\n return ReflectGet(target, key);\n }\n return ReflectGet(target, key, receiver);\n },\n set(target, key, value, receiver) {\n if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {\n return ReflectSet(target, key, roundToFloat16Bits(value));\n }\n return ReflectSet(target, key, value, receiver);\n },\n getOwnPropertyDescriptor(target, key) {\n if (isCanonicalIntegerIndexString(key) && ObjectHasOwn(target, key)) {\n const descriptor = ReflectGetOwnPropertyDescriptor(target, key);\n descriptor.value = convertToNumber(descriptor.value);\n return descriptor;\n }\n return ReflectGetOwnPropertyDescriptor(target, key);\n },\n defineProperty(target, key, descriptor) {\n if (\n isCanonicalIntegerIndexString(key) &&\n ObjectHasOwn(target, key) &&\n ObjectHasOwn(descriptor, \"value\")\n ) {\n descriptor.value = roundToFloat16Bits(descriptor.value);\n return ReflectDefineProperty(target, key, descriptor);\n }\n return ReflectDefineProperty(target, key, descriptor);\n },\n}));\nclass Float16Array {\n constructor(input, _byteOffset, _length) {\n let float16bitsArray;\n if (isFloat16Array(input)) {\n float16bitsArray = ReflectConstruct(NativeUint16Array, [getFloat16BitsArray(input)], new.target);\n } else if (isObject(input) && !isArrayBuffer(input)) {\n let list;\n let length;\n if (isNativeTypedArray(input)) {\n list = input;\n length = TypedArrayPrototypeGetLength(input);\n const buffer = TypedArrayPrototypeGetBuffer(input);\n const BufferConstructor = !isSharedArrayBuffer(buffer)\n ? (SpeciesConstructor(\n buffer,\n NativeArrayBuffer\n ))\n : NativeArrayBuffer;\n if (IsDetachedBuffer(buffer)) {\n throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);\n }\n if (isNativeBigIntTypedArray(input)) {\n throw NativeTypeError(CANNOT_MIX_BIGINT_AND_OTHER_TYPES);\n }\n const data = new BufferConstructor(\n length * BYTES_PER_ELEMENT\n );\n float16bitsArray = ReflectConstruct(NativeUint16Array, [data], new.target);\n } else {\n const iterator = input[SymbolIterator];\n if (iterator != null && typeof iterator !== \"function\") {\n throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE);\n }\n if (iterator != null) {\n if (isOrdinaryArray(input)) {\n list = input;\n length = input.length;\n } else {\n list = [... (input)];\n length = list.length;\n }\n } else {\n list = (input);\n length = ToLength(list.length);\n }\n float16bitsArray = ReflectConstruct(NativeUint16Array, [length], new.target);\n }\n for (let i = 0; i < length; ++i) {\n float16bitsArray[i] = roundToFloat16Bits(list[i]);\n }\n } else {\n float16bitsArray = ReflectConstruct(NativeUint16Array, arguments, new.target);\n }\n const proxy = (new NativeProxy(float16bitsArray, handler));\n WeakMapPrototypeSet(float16bitsArrays, proxy, float16bitsArray);\n return proxy;\n }\n static from(src, ...opts) {\n const Constructor = this;\n if (!ReflectHas(Constructor, brand)) {\n throw NativeTypeError(\n THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY\n );\n }\n if (Constructor === Float16Array) {\n if (isFloat16Array(src) && opts.length === 0) {\n const float16bitsArray = getFloat16BitsArray(src);\n const uint16 = new NativeUint16Array(\n TypedArrayPrototypeGetBuffer(float16bitsArray),\n TypedArrayPrototypeGetByteOffset(float16bitsArray),\n TypedArrayPrototypeGetLength(float16bitsArray)\n );\n return new Float16Array(\n TypedArrayPrototypeGetBuffer(TypedArrayPrototypeSlice(uint16))\n );\n }\n if (opts.length === 0) {\n return new Float16Array(\n TypedArrayPrototypeGetBuffer(\n Uint16ArrayFrom(src, roundToFloat16Bits)\n )\n );\n }\n const mapFunc = opts[0];\n const thisArg = opts[1];\n return new Float16Array(\n TypedArrayPrototypeGetBuffer(\n Uint16ArrayFrom(src, function (val, ...args) {\n return roundToFloat16Bits(\n ReflectApply(mapFunc, this, [val, ...safeIfNeeded(args)])\n );\n }, thisArg)\n )\n );\n }\n let list;\n let length;\n const iterator = src[SymbolIterator];\n if (iterator != null && typeof iterator !== \"function\") {\n throw NativeTypeError(ITERATOR_PROPERTY_IS_NOT_CALLABLE);\n }\n if (iterator != null) {\n if (isOrdinaryArray(src)) {\n list = src;\n length = src.length;\n } else if (isOrdinaryNativeTypedArray(src)) {\n list = src;\n length = TypedArrayPrototypeGetLength(src);\n } else {\n list = [...src];\n length = list.length;\n }\n } else {\n if (src == null) {\n throw NativeTypeError(\n CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT\n );\n }\n list = NativeObject(src);\n length = ToLength(list.length);\n }\n const array = new Constructor(length);\n if (opts.length === 0) {\n for (let i = 0; i < length; ++i) {\n array[i] = (list[i]);\n }\n } else {\n const mapFunc = opts[0];\n const thisArg = opts[1];\n for (let i = 0; i < length; ++i) {\n array[i] = ReflectApply(mapFunc, thisArg, [list[i], i]);\n }\n }\n return array;\n }\n static of(...items) {\n const Constructor = this;\n if (!ReflectHas(Constructor, brand)) {\n throw NativeTypeError(\n THIS_CONSTRUCTOR_IS_NOT_A_SUBCLASS_OF_FLOAT16ARRAY\n );\n }\n const length = items.length;\n if (Constructor === Float16Array) {\n const proxy = new Float16Array(length);\n const float16bitsArray = getFloat16BitsArray(proxy);\n for (let i = 0; i < length; ++i) {\n float16bitsArray[i] = roundToFloat16Bits(items[i]);\n }\n return proxy;\n }\n const array = new Constructor(length);\n for (let i = 0; i < length; ++i) {\n array[i] = items[i];\n }\n return array;\n }\n keys() {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n return TypedArrayPrototypeKeys(float16bitsArray);\n }\n values() {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n return wrap((function* () {\n for (const val of TypedArrayPrototypeValues(float16bitsArray)) {\n yield convertToNumber(val);\n }\n })());\n }\n entries() {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n return wrap((function* () {\n for (const [i, val] of TypedArrayPrototypeEntries(float16bitsArray)) {\n yield ([i, convertToNumber(val)]);\n }\n })());\n }\n at(index) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const relativeIndex = ToIntegerOrInfinity(index);\n const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex;\n if (k < 0 || k >= length) {\n return;\n }\n return convertToNumber(float16bitsArray[k]);\n }\n map(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);\n if (Constructor === Float16Array) {\n const proxy = new Float16Array(length);\n const array = getFloat16BitsArray(proxy);\n for (let i = 0; i < length; ++i) {\n const val = convertToNumber(float16bitsArray[i]);\n array[i] = roundToFloat16Bits(\n ReflectApply(callback, thisArg, [val, i, this])\n );\n }\n return proxy;\n }\n const array = new Constructor(length);\n assertSpeciesTypedArray(array, length);\n for (let i = 0; i < length; ++i) {\n const val = convertToNumber(float16bitsArray[i]);\n array[i] = ReflectApply(callback, thisArg, [val, i, this]);\n }\n return (array);\n }\n filter(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n const kept = [];\n for (let i = 0; i < length; ++i) {\n const val = convertToNumber(float16bitsArray[i]);\n if (ReflectApply(callback, thisArg, [val, i, this])) {\n ArrayPrototypePush(kept, val);\n }\n }\n const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);\n const array = new Constructor(kept);\n assertSpeciesTypedArray(array);\n return (array);\n }\n reduce(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n if (length === 0 && opts.length === 0) {\n throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE);\n }\n let accumulator, start;\n if (opts.length === 0) {\n accumulator = convertToNumber(float16bitsArray[0]);\n start = 1;\n } else {\n accumulator = opts[0];\n start = 0;\n }\n for (let i = start; i < length; ++i) {\n accumulator = callback(\n accumulator,\n convertToNumber(float16bitsArray[i]),\n i,\n this\n );\n }\n return accumulator;\n }\n reduceRight(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n if (length === 0 && opts.length === 0) {\n throw NativeTypeError(REDUCE_OF_EMPTY_ARRAY_WITH_NO_INITIAL_VALUE);\n }\n let accumulator, start;\n if (opts.length === 0) {\n accumulator = convertToNumber(float16bitsArray[length - 1]);\n start = length - 2;\n } else {\n accumulator = opts[0];\n start = length - 1;\n }\n for (let i = start; i >= 0; --i) {\n accumulator = callback(\n accumulator,\n convertToNumber(float16bitsArray[i]),\n i,\n this\n );\n }\n return accumulator;\n }\n forEach(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = 0; i < length; ++i) {\n ReflectApply(callback, thisArg, [\n convertToNumber(float16bitsArray[i]),\n i,\n this,\n ]);\n }\n }\n find(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = 0; i < length; ++i) {\n const value = convertToNumber(float16bitsArray[i]);\n if (ReflectApply(callback, thisArg, [value, i, this])) {\n return value;\n }\n }\n }\n findIndex(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = 0; i < length; ++i) {\n const value = convertToNumber(float16bitsArray[i]);\n if (ReflectApply(callback, thisArg, [value, i, this])) {\n return i;\n }\n }\n return -1;\n }\n findLast(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = length - 1; i >= 0; --i) {\n const value = convertToNumber(float16bitsArray[i]);\n if (ReflectApply(callback, thisArg, [value, i, this])) {\n return value;\n }\n }\n }\n findLastIndex(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = length - 1; i >= 0; --i) {\n const value = convertToNumber(float16bitsArray[i]);\n if (ReflectApply(callback, thisArg, [value, i, this])) {\n return i;\n }\n }\n return -1;\n }\n every(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = 0; i < length; ++i) {\n if (\n !ReflectApply(callback, thisArg, [\n convertToNumber(float16bitsArray[i]),\n i,\n this,\n ])\n ) {\n return false;\n }\n }\n return true;\n }\n some(callback, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const thisArg = opts[0];\n for (let i = 0; i < length; ++i) {\n if (\n ReflectApply(callback, thisArg, [\n convertToNumber(float16bitsArray[i]),\n i,\n this,\n ])\n ) {\n return true;\n }\n }\n return false;\n }\n set(input, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const targetOffset = ToIntegerOrInfinity(opts[0]);\n if (targetOffset < 0) {\n throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);\n }\n if (input == null) {\n throw NativeTypeError(\n CANNOT_CONVERT_UNDEFINED_OR_NULL_TO_OBJECT\n );\n }\n if (isNativeBigIntTypedArray(input)) {\n throw NativeTypeError(\n CANNOT_MIX_BIGINT_AND_OTHER_TYPES\n );\n }\n if (isFloat16Array(input)) {\n return TypedArrayPrototypeSet(\n getFloat16BitsArray(this),\n getFloat16BitsArray(input),\n targetOffset\n );\n }\n if (isNativeTypedArray(input)) {\n const buffer = TypedArrayPrototypeGetBuffer(input);\n if (IsDetachedBuffer(buffer)) {\n throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);\n }\n }\n const targetLength = TypedArrayPrototypeGetLength(float16bitsArray);\n const src = NativeObject(input);\n const srcLength = ToLength(src.length);\n if (targetOffset === Infinity || srcLength + targetOffset > targetLength) {\n throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);\n }\n for (let i = 0; i < srcLength; ++i) {\n float16bitsArray[i + targetOffset] = roundToFloat16Bits(src[i]);\n }\n }\n reverse() {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n TypedArrayPrototypeReverse(float16bitsArray);\n return this;\n }\n fill(value, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n TypedArrayPrototypeFill(\n float16bitsArray,\n roundToFloat16Bits(value),\n ...safeIfNeeded(opts)\n );\n return this;\n }\n copyWithin(target, start, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n TypedArrayPrototypeCopyWithin(float16bitsArray, target, start, ...safeIfNeeded(opts));\n return this;\n }\n sort(compareFn) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const sortCompare = compareFn !== undefined ? compareFn : defaultCompare;\n TypedArrayPrototypeSort(float16bitsArray, (x, y) => {\n return sortCompare(convertToNumber(x), convertToNumber(y));\n });\n return this;\n }\n slice(start, end) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);\n if (Constructor === Float16Array) {\n const uint16 = new NativeUint16Array(\n TypedArrayPrototypeGetBuffer(float16bitsArray),\n TypedArrayPrototypeGetByteOffset(float16bitsArray),\n TypedArrayPrototypeGetLength(float16bitsArray)\n );\n return new Float16Array(\n TypedArrayPrototypeGetBuffer(\n TypedArrayPrototypeSlice(uint16, start, end)\n )\n );\n }\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n const relativeStart = ToIntegerOrInfinity(start);\n const relativeEnd = end === undefined ? length : ToIntegerOrInfinity(end);\n let k;\n if (relativeStart === -Infinity) {\n k = 0;\n } else if (relativeStart < 0) {\n k = length + relativeStart > 0 ? length + relativeStart : 0;\n } else {\n k = length < relativeStart ? length : relativeStart;\n }\n let final;\n if (relativeEnd === -Infinity) {\n final = 0;\n } else if (relativeEnd < 0) {\n final = length + relativeEnd > 0 ? length + relativeEnd : 0;\n } else {\n final = length < relativeEnd ? length : relativeEnd;\n }\n const count = final - k > 0 ? final - k : 0;\n const array = new Constructor(count);\n assertSpeciesTypedArray(array, count);\n if (count === 0) {\n return array;\n }\n const buffer = TypedArrayPrototypeGetBuffer(float16bitsArray);\n if (IsDetachedBuffer(buffer)) {\n throw NativeTypeError(ATTEMPTING_TO_ACCESS_DETACHED_ARRAYBUFFER);\n }\n let n = 0;\n while (k < final) {\n array[n] = convertToNumber(float16bitsArray[k]);\n ++k;\n ++n;\n }\n return (array);\n }\n subarray(begin, end) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const Constructor = SpeciesConstructor(float16bitsArray, Float16Array);\n const uint16 = new NativeUint16Array(\n TypedArrayPrototypeGetBuffer(float16bitsArray),\n TypedArrayPrototypeGetByteOffset(float16bitsArray),\n TypedArrayPrototypeGetLength(float16bitsArray)\n );\n const uint16Subarray = TypedArrayPrototypeSubarray(uint16, begin, end);\n const array = new Constructor(\n TypedArrayPrototypeGetBuffer(uint16Subarray),\n TypedArrayPrototypeGetByteOffset(uint16Subarray),\n TypedArrayPrototypeGetLength(uint16Subarray)\n );\n assertSpeciesTypedArray(array);\n return (array);\n }\n indexOf(element, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n let from = ToIntegerOrInfinity(opts[0]);\n if (from === Infinity) {\n return -1;\n }\n if (from < 0) {\n from += length;\n if (from < 0) {\n from = 0;\n }\n }\n for (let i = from; i < length; ++i) {\n if (\n ObjectHasOwn(float16bitsArray, i) &&\n convertToNumber(float16bitsArray[i]) === element\n ) {\n return i;\n }\n }\n return -1;\n }\n lastIndexOf(element, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n let from = opts.length >= 1 ? ToIntegerOrInfinity(opts[0]) : length - 1;\n if (from === -Infinity) {\n return -1;\n }\n if (from >= 0) {\n from = from < length - 1 ? from : length - 1;\n } else {\n from += length;\n }\n for (let i = from; i >= 0; --i) {\n if (\n ObjectHasOwn(float16bitsArray, i) &&\n convertToNumber(float16bitsArray[i]) === element\n ) {\n return i;\n }\n }\n return -1;\n }\n includes(element, ...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const length = TypedArrayPrototypeGetLength(float16bitsArray);\n let from = ToIntegerOrInfinity(opts[0]);\n if (from === Infinity) {\n return false;\n }\n if (from < 0) {\n from += length;\n if (from < 0) {\n from = 0;\n }\n }\n const isNaN = NumberIsNaN(element);\n for (let i = from; i < length; ++i) {\n const value = convertToNumber(float16bitsArray[i]);\n if (isNaN && NumberIsNaN(value)) {\n return true;\n }\n if (value === element) {\n return true;\n }\n }\n return false;\n }\n join(separator) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const array = copyToArray(float16bitsArray);\n return ArrayPrototypeJoin(array, separator);\n }\n toLocaleString(...opts) {\n assertFloat16Array(this);\n const float16bitsArray = getFloat16BitsArray(this);\n const array = copyToArray(float16bitsArray);\n return ArrayPrototypeToLocaleString(array, ...safeIfNeeded(opts));\n }\n get [SymbolToStringTag]() {\n if (isFloat16Array(this)) {\n return (\"Float16Array\");\n }\n }\n}\nObjectDefineProperty(Float16Array, \"BYTES_PER_ELEMENT\", {\n value: BYTES_PER_ELEMENT,\n});\nObjectDefineProperty(Float16Array, brand, {});\nReflectSetPrototypeOf(Float16Array, TypedArray);\nconst Float16ArrayPrototype = Float16Array.prototype;\nObjectDefineProperty(Float16ArrayPrototype, \"BYTES_PER_ELEMENT\", {\n value: BYTES_PER_ELEMENT,\n});\nObjectDefineProperty(Float16ArrayPrototype, SymbolIterator, {\n value: Float16ArrayPrototype.values,\n writable: true,\n configurable: true,\n});\nReflectSetPrototypeOf(Float16ArrayPrototype, TypedArrayPrototype);\n\nfunction isTypedArray(target) {\n return isNativeTypedArray(target) || isFloat16Array(target);\n}\n\nfunction getFloat16(dataView, byteOffset, ...opts) {\n return convertToNumber(\n DataViewPrototypeGetUint16(dataView, byteOffset, ...safeIfNeeded(opts))\n );\n}\nfunction setFloat16(dataView, byteOffset, value, ...opts) {\n return DataViewPrototypeSetUint16(\n dataView,\n byteOffset,\n roundToFloat16Bits(value),\n ...safeIfNeeded(opts)\n );\n}\n\nfunction hfround(x) {\n const number = +x;\n if (!NumberIsFinite(number) || number === 0) {\n return number;\n }\n const x16 = roundToFloat16Bits(number);\n return convertToNumber(x16);\n}\n\nexport { Float16Array, getFloat16, hfround, isFloat16Array, isTypedArray, setFloat16 };\n"],"mappings":";AAAA;AAAA,G,CAAA,yFAEA,MAAMA,qBAAqB,GAAG,uBAAuB;AACrD,MAAMC,iCAAiC,GAAG,mCAAmC;AAC7E,MAAMC,kDAAkD;AACtD,oDAAoD;AACtD,MAAMC,+CAA+C;AACnD,iDAAiD;AACnD,MAAMC,kDAAkD;AACtD,qDAAqD;AACvD,MAAMC,wEAAwE;AAC5E,0EAA0E;AAC5E,MAAMC,yCAAyC;AAC7C,2CAA2C;AAC7C,MAAMC,0CAA0C;AAC9C,4CAA4C;AAC9C,MAAMC,iCAAiC;AACrC,6DAA6D;AAC/D,MAAMC,iCAAiC,GAAG,qCAAqC;AAC/E,MAAMC,2CAA2C;AAC/C,6CAA6C;AAC/C,MAAMC,uBAAuB,GAAG,yBAAyB;;AAEzD,SAASC,WAAW,CAACC,MAAM,EAAE;EAC3B,OAAO,CAACC,OAAO,EAAE,GAAGC,IAAI,KAAK;IAC3B,OAAOC,YAAY,CAACH,MAAM,EAAEC,OAAO,EAAEC,IAAI,CAAC;EAC5C,CAAC;AACH;AACA,SAASE,iBAAiB,CAACJ,MAAM,EAAEK,GAAG,EAAE;EACtC,OAAON,WAAW;EAChBO,+BAA+B;EAC7BN,MAAM;EACNK,GAAG,CACJ;EAACE,GAAG,CACN;;AACH;AACA,MAAM;EACJC,KAAK,EAAEL,YAAY;EACnBM,SAAS,EAAEC,gBAAgB;EAC3BC,cAAc,EAAEC,qBAAqB;EACrCL,GAAG,EAAEM,UAAU;EACfC,wBAAwB,EAAER,+BAA+B;EACzDS,cAAc,EAAEC,qBAAqB;EACrCC,GAAG,EAAEC,UAAU;EACfC,OAAO,EAAEC,cAAc;EACvBC,GAAG,EAAEC,UAAU;EACfC,cAAc,EAAEC;AAClB,CAAC,GAAGC,OAAO;AACX,MAAMC,WAAW,GAAGC,KAAK;AACzB,MAAM;EACJC,gBAAgB,EAAEA,gBAAgB;EAClCC,QAAQ,EAAEC,cAAc;EACxBC,KAAK,EAAEC;AACT,CAAC,GAAGC,MAAM;AACV,MAAM;EACJC,QAAQ,EAAEC,cAAc;EACxBC,OAAO,EAAEC,aAAa;EACtBC,WAAW,EAAEC,iBAAiB;EAC9BC,GAAG,EAAEC;AACP,CAAC,GAAGC,MAAM;AACV,MAAMC,YAAY,GAAGC,MAAM;AAC3B,MAAM;EACJC,MAAM,EAAEC,YAAY;EACpBnC,cAAc,EAAEoC,oBAAoB;EACpCC,MAAM,EAAEC,YAAY;EACpBC,EAAE,EAAEC;AACN,CAAC,GAAGR,YAAY;AAChB,MAAMS,eAAe,GAAGT,YAAY,CAACU,SAAS;AAC9C,MAAMC,+BAA+B,GAAKF,eAAe,CAAEG,gBAAgB;AACvExD,WAAW,CAAGqD,eAAe,CAAEG,gBAAgB,CAAC;AAChD,CAACC,MAAM,EAAEnD,GAAG,KAAK;EACjB,IAAImD,MAAM,IAAI,IAAI,EAAE;IAClB,MAAMC,eAAe;IACnB/D,0CAA0C,CAC3C;;EACH;EACA,IAAIM,MAAM,GAAG2C,YAAY,CAACa,MAAM,CAAC;EACjC,GAAG;IACD,MAAME,UAAU,GAAGpD,+BAA+B,CAACN,MAAM,EAAEK,GAAG,CAAC;IAC/D,IAAIqD,UAAU,KAAKC,SAAS,EAAE;MAC5B,IAAIC,YAAY,CAACF,UAAU,EAAE,KAAK,CAAC,EAAE;QACnC,OAAOA,UAAU,CAACnD,GAAG;MACvB;MACA;IACF;EACF,CAAC,QAAQ,CAACP,MAAM,GAAGgB,qBAAqB,CAAChB,MAAM,CAAC,MAAM,IAAI;AAC5D,CAAC;AACH,MAAM4D,YAAY,GAAKjB,YAAY,CAAEkB,MAAM;AACzC9D,WAAW,CAACqD,eAAe,CAACU,cAAc,CAAC;AAC7C,MAAMC,WAAW,GAAGC,KAAK;AACzB,MAAMC,YAAY,GAAGF,WAAW,CAACG,OAAO;AACxC,MAAMC,cAAc,GAAGJ,WAAW,CAACV,SAAS;AAC5C,MAAMe,kBAAkB,GAAGrE,WAAW,CAACoE,cAAc,CAACE,IAAI,CAAC;AAC3D,MAAMC,kBAAkB,GAAGvE,WAAW,CAACoE,cAAc,CAACI,IAAI,CAAC;AAC3D,MAAMC,4BAA4B,GAAGzE,WAAW;AAC9CoE,cAAc,CAACM,cAAc,CAC9B;;AACD,MAAMC,kCAAkC,GAAGP,cAAc,CAAChC,cAAc,CAAC;AACzE,MAAMwC,4BAA4B,GAAG5E,WAAW,CAAC2E,kCAAkC,CAAC;AACpF,MAAME,SAAS,GAAGC,IAAI,CAACC,KAAK;AAC5B,MAAMC,iBAAiB,GAAGC,WAAW;AACrC,MAAMC,iBAAiB,GAAGF,iBAAiB,CAACG,MAAM;AAClD,MAAMC,oBAAoB,GAAGJ,iBAAiB,CAAC1B,SAAS;AACxD,MAAM+B,yBAAyB,GAAGrF,WAAW,CAACoF,oBAAoB,CAACE,KAAK,CAAC;AACzE,MAAMC,iCAAiC,GAAGlF,iBAAiB,CAAC+E,oBAAoB,EAAE,YAAY,CAAC;AAC/F,MAAMI,uBAAuB,GAAG,OAAOC,iBAAiB,KAAK,WAAW,GAAGA,iBAAiB,GAAG,IAAI;AACnG,MAAMC,uCAAuC,GAAGF,uBAAuB;AAClEnF,iBAAiB,CAACmF,uBAAuB,CAAClC,SAAS,EAAE,YAAY,CAAC;AACvE,MAAMqC,UAAU,GAAG1E,qBAAqB,CAAC2E,UAAU,CAAC;AACpD,MAAMC,cAAc,GAAGF,UAAU,CAACG,IAAI;AACtC,MAAMC,mBAAmB,GAAGJ,UAAU,CAACrC,SAAS;AAChD,MAAM0C,uCAAuC,GAAGD,mBAAmB,CAAC3D,cAAc,CAAC;AACnF,MAAM6D,uBAAuB,GAAGjG,WAAW,CAAC+F,mBAAmB,CAACG,IAAI,CAAC;AACrE,MAAMC,yBAAyB,GAAGnG,WAAW;AAC3C+F,mBAAmB,CAACK,MAAM,CAC3B;;AACD,MAAMC,0BAA0B,GAAGrG,WAAW;AAC5C+F,mBAAmB,CAACO,OAAO,CAC5B;;AACD,MAAMC,sBAAsB,GAAGvG,WAAW,CAAC+F,mBAAmB,CAACzE,GAAG,CAAC;AACnE,MAAMkF,0BAA0B,GAAGxG,WAAW;AAC5C+F,mBAAmB,CAACU,OAAO,CAC5B;;AACD,MAAMC,uBAAuB,GAAG1G,WAAW,CAAC+F,mBAAmB,CAACY,IAAI,CAAC;AACrE,MAAMC,6BAA6B,GAAG5G,WAAW;AAC/C+F,mBAAmB,CAACc,UAAU,CAC/B;;AACD,MAAMC,uBAAuB,GAAG9G,WAAW,CAAC+F,mBAAmB,CAACgB,IAAI,CAAC;AACrE,MAAMC,wBAAwB,GAAGhH,WAAW,CAAC+F,mBAAmB,CAACT,KAAK,CAAC;AACvE,MAAM2B,2BAA2B,GAAGjH,WAAW;AAC7C+F,mBAAmB,CAACmB,QAAQ,CAC7B;;AACD,MAAMC,4BAA4B,GAAG9G,iBAAiB;AACpD0F,mBAAmB;AACnB,QAAQ,CACT;;AACD,MAAMqB,gCAAgC,GAAG/G,iBAAiB;AACxD0F,mBAAmB;AACnB,YAAY,CACb;;AACD,MAAMsB,4BAA4B,GAAGhH,iBAAiB;AACpD0F,mBAAmB;AACnB,QAAQ,CACT;;AACD,MAAMuB,uCAAuC,GAAGjH,iBAAiB;AAC/D0F,mBAAmB;AACnBvD,iBAAiB,CAClB;;AACD,MAAM+E,iBAAiB,GAAGC,WAAW;AACrC,MAAMC,eAAe,GAAG,CAAC,GAAGtH,IAAI,KAAK;EACnC,OAAOC,YAAY,CAACyF,cAAc,EAAE0B,iBAAiB,EAAEpH,IAAI,CAAC;AAC9D,CAAC;AACD,MAAMuH,iBAAiB,GAAGC,WAAW;AACrC,MAAMC,kBAAkB,GAAGC,YAAY;AACvC,MAAMC,sBAAsB,GAAG7G,qBAAqB,CAAC,EAAE,CAACmB,cAAc,CAAC,EAAE,CAAC;AAC1E,MAAM2F,0BAA0B,GAAG/H,WAAW,CAAC8H,sBAAsB,CAACE,IAAI,CAAC;AAC3E,MAAMC,sBAAsB,GAAGjI,WAAW,CAAE,aAAa,CAAC,CAAC,EAAG,CAACgI,IAAI,CAAC;AACpE,MAAME,iBAAiB,GAAGjH,qBAAqB,CAAC6G,sBAAsB,CAAC;AACvE,MAAMK,iBAAiB,GAAGC,QAAQ,CAAC9E,SAAS;AAC5C,MAAM+E,0BAA0B,GAAGrI,WAAW;AAC5CmI,iBAAiB,CAACG,SAAS,CAC5B;;AACD,MAAMC,0BAA0B,GAAGvI,WAAW;AAC5CmI,iBAAiB,CAACK,SAAS,CAC5B;;AACD,MAAM9E,eAAe,GAAG+E,SAAS;AACjC,MAAMC,gBAAgB,GAAGC,UAAU;AACnC,MAAMC,aAAa,GAAGC,OAAO;AAC7B,MAAMC,gBAAgB,GAAGF,aAAa,CAACtF,SAAS;AAChD,MAAMyF,mBAAmB,GAAG/I,WAAW,CAAC8I,gBAAgB,CAACE,GAAG,CAAC;AAC7D,MAAMC,mBAAmB,GAAGjJ,WAAW,CAAC8I,gBAAgB,CAAC5H,GAAG,CAAC;AAC7D,MAAMgI,aAAa,GAAGC,OAAO;AAC7B,MAAMC,gBAAgB,GAAGF,aAAa,CAAC5F,SAAS;AAChD,MAAM+F,mBAAmB,GAAGrJ,WAAW,CAACoJ,gBAAgB,CAAC5I,GAAG,CAAC;AAC7D,MAAM8I,mBAAmB,GAAGtJ,WAAW,CAACoJ,gBAAgB,CAAClI,GAAG,CAAC;AAC7D,MAAMqI,mBAAmB,GAAGvJ,WAAW,CAACoJ,gBAAgB,CAAC9H,GAAG,CAAC;;AAE7D,MAAMkI,cAAc,GAAG,IAAIN,aAAa,EAAE;AAC1C,MAAMO,qBAAqB,GAAG1G,YAAY,CAAC,IAAI,EAAE;EAC/CiF,IAAI,EAAE;IACJ0B,KAAK,EAAE,SAAS1B,IAAI,GAAG;MACrB,MAAM2B,aAAa,GAAGN,mBAAmB,CAACG,cAAc,EAAE,IAAI,CAAC;MAC/D,OAAOzB,0BAA0B,CAAC4B,aAAa,CAAC;IAClD;EACF,CAAC;EACD,CAACvH,cAAc,GAAG;IAChBsH,KAAK,EAAE,SAAStD,MAAM,GAAG;MACvB,OAAO,IAAI;IACb;EACF;AACF,CAAC,CAAC;AACF,SAASwD,YAAY,CAACC,KAAK,EAAE;EAC3B,IAAIA,KAAK,CAACzH,cAAc,CAAC,KAAKuC,kCAAkC,EAAE;IAChE,OAAOkF,KAAK;EACd;EACA,MAAMC,IAAI,GAAG/G,YAAY,CAAC0G,qBAAqB,CAAC;EAChDF,mBAAmB,CAACC,cAAc,EAAEM,IAAI,EAAElF,4BAA4B,CAACiF,KAAK,CAAC,CAAC;EAC9E,OAAOC,IAAI;AACb;AACA,MAAMC,UAAU,GAAG,IAAIb,aAAa,EAAE;AACtC,MAAMc,2BAA2B,GAAGjH,YAAY,CAACmF,iBAAiB,EAAE;EAClEF,IAAI,EAAE;IACJ0B,KAAK,EAAE,SAAS1B,IAAI,GAAG;MACrB,MAAMiC,SAAS,GAAGZ,mBAAmB,CAACU,UAAU,EAAE,IAAI,CAAC;MACvD,OAAO9B,sBAAsB,CAACgC,SAAS,CAAC;IAC1C,CAAC;IACDC,QAAQ,EAAE,IAAI;IACdC,YAAY,EAAE;EAChB;AACF,CAAC,CAAC;AACF,KAAK,MAAM7J,GAAG,IAAIe,cAAc,CAACyG,sBAAsB,CAAC,EAAE;EACxD,IAAIxH,GAAG,KAAK,MAAM,EAAE;IAClB;EACF;EACA0C,oBAAoB,CAACgH,2BAA2B,EAAE1J,GAAG,EAAEC,+BAA+B,CAACuH,sBAAsB,EAAExH,GAAG,CAAC,CAAC;AACtH;AACA,SAAS8J,IAAI,CAACH,SAAS,EAAE;EACvB,MAAMI,KAAK,GAAGtH,YAAY,CAACiH,2BAA2B,CAAC;EACvDT,mBAAmB,CAACQ,UAAU,EAAEM,KAAK,EAAEJ,SAAS,CAAC;EACjD,OAAOI,KAAK;AACd;;AAEA,SAASC,QAAQ,CAACZ,KAAK,EAAE;EACvB,OAAQA,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ;EACjD,OAAOA,KAAK,KAAK,UAAU;AAC/B;AACA,SAASa,YAAY,CAACb,KAAK,EAAE;EAC3B,OAAOA,KAAK,KAAK,IAAI,IAAI,OAAOA,KAAK,KAAK,QAAQ;AACpD;AACA,SAASc,kBAAkB,CAACd,KAAK,EAAE;EACjC,OAAOpC,uCAAuC,CAACoC,KAAK,CAAC,KAAK9F,SAAS;AACrE;AACA,SAAS6G,wBAAwB,CAACf,KAAK,EAAE;EACvC,MAAMgB,cAAc,GAAGpD,uCAAuC,CAACoC,KAAK,CAAC;EACrE,OAAOgB,cAAc,KAAK,eAAe;EACvCA,cAAc,KAAK,gBAAgB;AACvC;AACA,SAASC,aAAa,CAACjB,KAAK,EAAE;EAC5B,IAAI;IACFnE,iCAAiC,CAAGmE,KAAK,CAAE;IAC3C,OAAO,IAAI;EACb,CAAC,CAAC,OAAOkB,CAAC,EAAE;IACV,OAAO,KAAK;EACd;AACF;AACA,SAASC,mBAAmB,CAACnB,KAAK,EAAE;EAClC,IAAIlE,uBAAuB,KAAK,IAAI,EAAE;IACpC,OAAO,KAAK;EACd;EACA,IAAI;IACFE,uCAAuC,CAAGgE,KAAK,CAAE;IACjD,OAAO,IAAI;EACb,CAAC,CAAC,OAAOkB,CAAC,EAAE;IACV,OAAO,KAAK;EACd;AACF;AACA,SAASE,eAAe,CAACpB,KAAK,EAAE;EAC9B,IAAI,CAACxF,YAAY,CAACwF,KAAK,CAAC,EAAE;IACxB,OAAO,KAAK;EACd;EACA,IAAIA,KAAK,CAACtH,cAAc,CAAC,KAAKuC,kCAAkC,EAAE;IAChE,OAAO,IAAI;EACb;EACA,MAAMxC,QAAQ,GAAGuH,KAAK,CAACtH,cAAc,CAAC,EAAE;EACxC,OAAOD,QAAQ,CAACK,iBAAiB,CAAC,KAAK,gBAAgB;AACzD;AACA,SAASuI,0BAA0B,CAACrB,KAAK,EAAE;EACzC,IAAI,CAACc,kBAAkB,CAACd,KAAK,CAAC,EAAE;IAC9B,OAAO,KAAK;EACd;EACA,IAAIA,KAAK,CAACtH,cAAc,CAAC,KAAK4D,uCAAuC,EAAE;IACrE,OAAO,IAAI;EACb;EACA,MAAM7D,QAAQ,GAAGuH,KAAK,CAACtH,cAAc,CAAC,EAAE;EACxC,OAAOD,QAAQ,CAACK,iBAAiB,CAAC,KAAK,gBAAgB;AACzD;AACA,SAASwI,6BAA6B,CAACtB,KAAK,EAAE;EAC5C,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;IAC7B,OAAO,KAAK;EACd;EACA,MAAMuB,MAAM,GAAG,CAACvB,KAAK;EACrB,IAAIA,KAAK,KAAKuB,MAAM,GAAG,EAAE,EAAE;IACzB,OAAO,KAAK;EACd;EACA,IAAI,CAAClJ,cAAc,CAACkJ,MAAM,CAAC,EAAE;IAC3B,OAAO,KAAK;EACd;EACA,OAAOA,MAAM,KAAKpG,SAAS,CAACoG,MAAM,CAAC;AACrC;;AAEA,MAAMC,KAAK,GAAGxI,SAAS,CAAC,kBAAkB,CAAC;AAC3C,SAASyI,oBAAoB,CAAClL,MAAM,EAAE;EACpC,IAAI,CAACsK,YAAY,CAACtK,MAAM,CAAC,EAAE;IACzB,OAAO,KAAK;EACd;EACA,MAAMqD,SAAS,GAAGrC,qBAAqB,CAAChB,MAAM,CAAC;EAC/C,IAAI,CAACsK,YAAY,CAACjH,SAAS,CAAC,EAAE;IAC5B,OAAO,KAAK;EACd;EACA,MAAM8H,WAAW,GAAG9H,SAAS,CAAC8H,WAAW;EACzC,IAAIA,WAAW,KAAKxH,SAAS,EAAE;IAC7B,OAAO,KAAK;EACd;EACA,IAAI,CAAC0G,QAAQ,CAACc,WAAW,CAAC,EAAE;IAC1B,MAAM1H,eAAe,CAACnE,+CAA+C,CAAC;EACxE;EACA,OAAO4B,UAAU,CAACiK,WAAW,EAAEF,KAAK,CAAC;AACvC;;AAEA,MAAMG,MAAM,GAAG,IAAIrG,iBAAiB,CAAC,CAAC,CAAC;AACvC,MAAMsG,SAAS,GAAG,IAAI1D,kBAAkB,CAACyD,MAAM,CAAC;AAChD,MAAME,UAAU,GAAG,IAAI7D,iBAAiB,CAAC2D,MAAM,CAAC;AAChD,MAAMG,SAAS,GAAG,IAAI9D,iBAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM+D,UAAU,GAAG,IAAI/D,iBAAiB,CAAC,GAAG,CAAC;AAC7C,KAAK,IAAIgE,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,GAAG,EAAE,EAAEA,CAAC,EAAE;EAC5B,MAAMd,CAAC,GAAGc,CAAC,GAAG,GAAG;EACjB,IAAId,CAAC,GAAG,CAAC,EAAE,EAAE;IACXY,SAAS,CAACE,CAAC,CAAC,GAAW,MAAM;IAC7BF,SAAS,CAACE,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM;IAC7BD,UAAU,CAACC,CAAC,CAAC,GAAW,EAAE;IAC1BD,UAAU,CAACC,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE;EAC5B,CAAC,MAAM,IAAId,CAAC,GAAG,CAAC,EAAE,EAAE;IAClBY,SAAS,CAACE,CAAC,CAAC,GAAY,MAAM,IAAK,CAACd,CAAC,GAAG,EAAG;IAC3CY,SAAS,CAACE,CAAC,GAAG,KAAK,CAAC,GAAI,MAAM,IAAK,CAACd,CAAC,GAAG,EAAG,GAAI,MAAM;IACrDa,UAAU,CAACC,CAAC,CAAC,GAAW,CAACd,CAAC,GAAG,CAAC;IAC9Ba,UAAU,CAACC,CAAC,GAAG,KAAK,CAAC,GAAG,CAACd,CAAC,GAAG,CAAC;EAChC,CAAC,MAAM,IAAIA,CAAC,IAAI,EAAE,EAAE;IAClBY,SAAS,CAACE,CAAC,CAAC,GAAad,CAAC,GAAG,EAAE,IAAK,EAAE;IACtCY,SAAS,CAACE,CAAC,GAAG,KAAK,CAAC,GAAKd,CAAC,GAAG,EAAE,IAAK,EAAE,GAAI,MAAM;IAChDa,UAAU,CAACC,CAAC,CAAC,GAAW,EAAE;IAC1BD,UAAU,CAACC,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE;EAC5B,CAAC,MAAM,IAAId,CAAC,GAAG,GAAG,EAAE;IAClBY,SAAS,CAACE,CAAC,CAAC,GAAW,MAAM;IAC7BF,SAAS,CAACE,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM;IAC7BD,UAAU,CAACC,CAAC,CAAC,GAAW,EAAE;IAC1BD,UAAU,CAACC,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE;EAC5B,CAAC,MAAM;IACLF,SAAS,CAACE,CAAC,CAAC,GAAW,MAAM;IAC7BF,SAAS,CAACE,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM;IAC7BD,UAAU,CAACC,CAAC,CAAC,GAAW,EAAE;IAC1BD,UAAU,CAACC,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE;EAC5B;AACF;AACA,SAASC,kBAAkB,CAACC,GAAG,EAAE;EAC/BN,SAAS,CAAC,CAAC,CAAC,GAAKM,GAAI;EACrB,MAAMC,CAAC,GAAGN,UAAU,CAAC,CAAC,CAAC;EACvB,MAAMX,CAAC,GAAIiB,CAAC,IAAI,EAAE,GAAI,KAAK;EAC3B,OAAOL,SAAS,CAACZ,CAAC,CAAC,IAAI,CAACiB,CAAC,GAAG,UAAU,KAAKJ,UAAU,CAACb,CAAC,CAAC,CAAC;AAC3D;AACA,MAAMkB,aAAa,GAAG,IAAIpE,iBAAiB,CAAC,IAAI,CAAC;AACjD,MAAMqE,aAAa,GAAG,IAAIrE,iBAAiB,CAAC,EAAE,CAAC;AAC/C,MAAMsE,WAAW,GAAG,IAAItE,iBAAiB,CAAC,EAAE,CAAC;AAC7C,KAAK,IAAIgE,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,IAAI,EAAE,EAAEA,CAAC,EAAE;EAC7B,IAAIO,CAAC,GAAGP,CAAC,IAAI,EAAE;EACf,IAAId,CAAC,GAAG,CAAC;EACT,OAAM,CAACqB,CAAC,GAAG,UAAU,MAAM,CAAC,EAAE;IAC5BA,CAAC,KAAK,CAAC;IACPrB,CAAC,IAAI,UAAU;EACjB;EACAqB,CAAC,IAAI,CAAC,UAAU;EAChBrB,CAAC,IAAI,UAAU;EACfkB,aAAa,CAACJ,CAAC,CAAC,GAAGO,CAAC,GAAGrB,CAAC;AAC1B;AACA,KAAK,IAAIc,CAAC,GAAG,IAAI,EAAEA,CAAC,GAAG,IAAI,EAAE,EAAEA,CAAC,EAAE;EAChCI,aAAa,CAACJ,CAAC,CAAC,GAAG,UAAU,IAAKA,CAAC,GAAG,IAAI,IAAK,EAAE,CAAC;AACpD;AACA,KAAK,IAAIA,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,EAAE,EAAE,EAAEA,CAAC,EAAE;EAC3BK,aAAa,CAACL,CAAC,CAAC,GAAGA,CAAC,IAAI,EAAE;AAC5B;AACAK,aAAa,CAAC,EAAE,CAAC,GAAG,UAAU;AAC9BA,aAAa,CAAC,EAAE,CAAC,GAAG,UAAU;AAC9B,KAAK,IAAIL,CAAC,GAAG,EAAE,EAAEA,CAAC,GAAG,EAAE,EAAE,EAAEA,CAAC,EAAE;EAC5BK,aAAa,CAACL,CAAC,CAAC,GAAG,UAAU,IAAKA,CAAC,GAAG,EAAE,IAAK,EAAE,CAAC;AAClD;AACAK,aAAa,CAAC,EAAE,CAAC,GAAG,UAAU;AAC9B,KAAK,IAAIL,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,EAAE,EAAE,EAAEA,CAAC,EAAE;EAC3B,IAAIA,CAAC,KAAK,EAAE,EAAE;IACZM,WAAW,CAACN,CAAC,CAAC,GAAG,IAAI;EACvB;AACF;AACA,SAASQ,eAAe,CAACC,WAAW,EAAE;EACpC,MAAMF,CAAC,GAAGE,WAAW,IAAI,EAAE;EAC3BZ,UAAU,CAAC,CAAC,CAAC,GAAGO,aAAa,CAACE,WAAW,CAACC,CAAC,CAAC,IAAIE,WAAW,GAAG,KAAK,CAAC,CAAC,GAAGJ,aAAa,CAACE,CAAC,CAAC;EACxF,OAAOX,SAAS,CAAC,CAAC,CAAC;AACrB;;AAEA,SAASc,mBAAmB,CAACnM,MAAM,EAAE;EACnC,MAAMgL,MAAM,GAAG,CAAChL,MAAM;EACtB,IAAIgC,WAAW,CAACgJ,MAAM,CAAC,IAAIA,MAAM,KAAK,CAAC,EAAE;IACvC,OAAO,CAAC;EACV;EACA,OAAOpG,SAAS,CAACoG,MAAM,CAAC;AAC1B;AACA,SAASoB,QAAQ,CAACpM,MAAM,EAAE;EACxB,MAAMqM,MAAM,GAAGF,mBAAmB,CAACnM,MAAM,CAAC;EAC1C,IAAIqM,MAAM,GAAG,CAAC,EAAE;IACd,OAAO,CAAC;EACV;EACA,OAAOA,MAAM,GAAGzK,gBAAgB;EAC5ByK,MAAM;EACNzK,gBAAgB;AACtB;AACA,SAAS0K,kBAAkB,CAACtM,MAAM,EAAEuM,kBAAkB,EAAE;EACtD,IAAI,CAAClC,QAAQ,CAACrK,MAAM,CAAC,EAAE;IACrB,MAAMyD,eAAe,CAACtE,qBAAqB,CAAC;EAC9C;EACA,MAAMgM,WAAW,GAAGnL,MAAM,CAACmL,WAAW;EACtC,IAAIA,WAAW,KAAKxH,SAAS,EAAE;IAC7B,OAAO4I,kBAAkB;EAC3B;EACA,IAAI,CAAClC,QAAQ,CAACc,WAAW,CAAC,EAAE;IAC1B,MAAM1H,eAAe,CAACnE,+CAA+C,CAAC;EACxE;EACA,MAAM8C,OAAO,GAAG+I,WAAW,CAAC9I,aAAa,CAAC;EAC1C,IAAID,OAAO,IAAI,IAAI,EAAE;IACnB,OAAOmK,kBAAkB;EAC3B;EACA,OAAOnK,OAAO;AAChB;AACA,SAASoK,gBAAgB,CAACpB,MAAM,EAAE;EAChC,IAAIR,mBAAmB,CAACQ,MAAM,CAAC,EAAE;IAC/B,OAAO,KAAK;EACd;EACA,IAAI;IACFhG,yBAAyB,CAACgG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACvC,OAAO,KAAK;EACd,CAAC,CAAC,OAAOT,CAAC,EAAE,CAAC;EACb,OAAO,IAAI;AACb;AACA,SAAS8B,cAAc,CAACC,CAAC,EAAEC,CAAC,EAAE;EAC5B,MAAMC,MAAM,GAAG5K,WAAW,CAAC0K,CAAC,CAAC;EAC7B,MAAMG,MAAM,GAAG7K,WAAW,CAAC2K,CAAC,CAAC;EAC7B,IAAIC,MAAM,IAAIC,MAAM,EAAE;IACpB,OAAO,CAAC;EACV;EACA,IAAID,MAAM,EAAE;IACV,OAAO,CAAC;EACV;EACA,IAAIC,MAAM,EAAE;IACV,OAAO,CAAC,CAAC;EACX;EACA,IAAIH,CAAC,GAAGC,CAAC,EAAE;IACT,OAAO,CAAC,CAAC;EACX;EACA,IAAID,CAAC,GAAGC,CAAC,EAAE;IACT,OAAO,CAAC;EACV;EACA,IAAID,CAAC,KAAK,CAAC,IAAIC,CAAC,KAAK,CAAC,EAAE;IACtB,MAAMG,WAAW,GAAG3J,QAAQ,CAACuJ,CAAC,EAAE,CAAC,CAAC;IAClC,MAAMK,WAAW,GAAG5J,QAAQ,CAACwJ,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAACG,WAAW,IAAIC,WAAW,EAAE;MAC/B,OAAO,CAAC,CAAC;IACX;IACA,IAAID,WAAW,IAAI,CAACC,WAAW,EAAE;MAC/B,OAAO,CAAC;IACV;EACF;EACA,OAAO,CAAC;AACV;;AAEA,MAAMC,iBAAiB,GAAG,CAAC;AAC3B,MAAMC,iBAAiB,GAAG,IAAIhE,aAAa,EAAE;AAC7C,SAASiE,cAAc,CAAClN,MAAM,EAAE;EAC9B,OAAOqJ,mBAAmB,CAAC4D,iBAAiB,EAAEjN,MAAM,CAAC;EAClD,CAACiF,iBAAiB,CAACjF,MAAM,CAAC,IAAIkL,oBAAoB,CAAClL,MAAM,CAAE;AAChE;AACA,SAASmN,kBAAkB,CAACnN,MAAM,EAAE;EAClC,IAAI,CAACkN,cAAc,CAAClN,MAAM,CAAC,EAAE;IAC3B,MAAMyD,eAAe,CAACrE,iCAAiC,CAAC;EAC1D;AACF;AACA,SAASgO,uBAAuB,CAACpN,MAAM,EAAEqN,KAAK,EAAE;EAC9C,MAAMC,oBAAoB,GAAGJ,cAAc,CAAClN,MAAM,CAAC;EACnD,MAAMuN,kBAAkB,GAAGhD,kBAAkB,CAACvK,MAAM,CAAC;EACrD,IAAI,CAACsN,oBAAoB,IAAI,CAACC,kBAAkB,EAAE;IAChD,MAAM9J,eAAe,CAAClE,kDAAkD,CAAC;EAC3E;EACA,IAAI,OAAO8N,KAAK,KAAK,QAAQ,EAAE;IAC7B,IAAIhB,MAAM;IACV,IAAIiB,oBAAoB,EAAE;MACxB,MAAME,gBAAgB,GAAGC,mBAAmB,CAACzN,MAAM,CAAC;MACpDqM,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IACzD,CAAC,MAAM;MACLnB,MAAM,GAAGjF,4BAA4B,CAACpH,MAAM,CAAC;IAC/C;IACA,IAAIqM,MAAM,GAAGgB,KAAK,EAAE;MAClB,MAAM5J,eAAe;MACnBjE,wEAAwE,CACzE;;IACH;EACF;EACA,IAAIgL,wBAAwB,CAACxK,MAAM,CAAC,EAAE;IACpC,MAAMyD,eAAe,CAAC9D,iCAAiC,CAAC;EAC1D;AACF;AACA,SAAS8N,mBAAmB,CAACC,OAAO,EAAE;EACpC,MAAMF,gBAAgB,GAAGpE,mBAAmB,CAAC6D,iBAAiB,EAAES,OAAO,CAAC;EACxE,IAAIF,gBAAgB,KAAK7J,SAAS,EAAE;IAClC,MAAMyH,MAAM,GAAGlE,4BAA4B,CAACsG,gBAAgB,CAAC;IAC7D,IAAIhB,gBAAgB,CAACpB,MAAM,CAAC,EAAE;MAC5B,MAAM3H,eAAe,CAAChE,yCAAyC,CAAC;IAClE;IACA,OAAO+N,gBAAgB;EACzB;EACA,MAAMpC,MAAM,GAAKsC,OAAO,CAAEtC,MAAM;EAChC,IAAIoB,gBAAgB,CAACpB,MAAM,CAAC,EAAE;IAC5B,MAAM3H,eAAe,CAAChE,yCAAyC,CAAC;EAClE;EACA,MAAMkO,MAAM,GAAGjN,gBAAgB,CAACkN,YAAY,EAAE;EAC5CxC,MAAM;EACJsC,OAAO,CAAEG,UAAU;EACnBH,OAAO,CAAErB,MAAM,CAClB;EAAEqB,OAAO,CAACvC,WAAW,CAAC;EACvB,OAAO/B,mBAAmB,CAAC6D,iBAAiB,EAAEU,MAAM,CAAC;AACvD;AACA,SAASG,WAAW,CAACN,gBAAgB,EAAE;EACrC,MAAMnB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;EAC7D,MAAM5D,KAAK,GAAG,EAAE;EAChB,KAAK,IAAI6B,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;IAC/B7B,KAAK,CAAC6B,CAAC,CAAC,GAAGQ,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;EACjD;EACA,OAAO7B,KAAK;AACd;AACA,MAAMmE,0BAA0B,GAAG,IAAIpF,aAAa,EAAE;AACtD,KAAK,MAAMtI,GAAG,IAAIe,cAAc,CAAC0E,mBAAmB,CAAC,EAAE;EACrD,IAAIzF,GAAG,KAAKkC,iBAAiB,EAAE;IAC7B;EACF;EACA,MAAMmB,UAAU,GAAGpD,+BAA+B,CAACwF,mBAAmB,EAAEzF,GAAG,CAAC;EAC5E,IAAIuD,YAAY,CAACF,UAAU,EAAE,KAAK,CAAC,IAAI,OAAOA,UAAU,CAACnD,GAAG,KAAK,UAAU,EAAE;IAC3EuI,mBAAmB,CAACiF,0BAA0B,EAAErK,UAAU,CAACnD,GAAG,CAAC;EACjE;AACF;AACA,MAAMyN,OAAO,GAAG/K,YAAY,CAAG;EAC7B1C,GAAG,CAACP,MAAM,EAAEK,GAAG,EAAE4N,QAAQ,EAAE;IACzB,IAAIlD,6BAA6B,CAAC1K,GAAG,CAAC,IAAIuD,YAAY,CAAC5D,MAAM,EAAEK,GAAG,CAAC,EAAE;MACnE,OAAO4L,eAAe,CAACpL,UAAU,CAACb,MAAM,EAAEK,GAAG,CAAC,CAAC;IACjD;IACA,IAAI2I,mBAAmB,CAAC+E,0BAA0B,EAAEzK,+BAA+B,CAACtD,MAAM,EAAEK,GAAG,CAAC,CAAC,EAAE;MACjG,OAAOQ,UAAU,CAACb,MAAM,EAAEK,GAAG,CAAC;IAChC;IACA,OAAOQ,UAAU,CAACb,MAAM,EAAEK,GAAG,EAAE4N,QAAQ,CAAC;EAC1C,CAAC;EACD5M,GAAG,CAACrB,MAAM,EAAEK,GAAG,EAAEoJ,KAAK,EAAEwE,QAAQ,EAAE;IAChC,IAAIlD,6BAA6B,CAAC1K,GAAG,CAAC,IAAIuD,YAAY,CAAC5D,MAAM,EAAEK,GAAG,CAAC,EAAE;MACnE,OAAOiB,UAAU,CAACtB,MAAM,EAAEK,GAAG,EAAEqL,kBAAkB,CAACjC,KAAK,CAAC,CAAC;IAC3D;IACA,OAAOnI,UAAU,CAACtB,MAAM,EAAEK,GAAG,EAAEoJ,KAAK,EAAEwE,QAAQ,CAAC;EACjD,CAAC;EACDnN,wBAAwB,CAACd,MAAM,EAAEK,GAAG,EAAE;IACpC,IAAI0K,6BAA6B,CAAC1K,GAAG,CAAC,IAAIuD,YAAY,CAAC5D,MAAM,EAAEK,GAAG,CAAC,EAAE;MACnE,MAAMqD,UAAU,GAAGpD,+BAA+B,CAACN,MAAM,EAAEK,GAAG,CAAC;MAC/DqD,UAAU,CAAC+F,KAAK,GAAGwC,eAAe,CAACvI,UAAU,CAAC+F,KAAK,CAAC;MACpD,OAAO/F,UAAU;IACnB;IACA,OAAOpD,+BAA+B,CAACN,MAAM,EAAEK,GAAG,CAAC;EACrD,CAAC;EACDM,cAAc,CAACX,MAAM,EAAEK,GAAG,EAAEqD,UAAU,EAAE;IACtC;IACEqH,6BAA6B,CAAC1K,GAAG,CAAC;IAClCuD,YAAY,CAAC5D,MAAM,EAAEK,GAAG,CAAC;IACzBuD,YAAY,CAACF,UAAU,EAAE,OAAO,CAAC;IACjC;MACAA,UAAU,CAAC+F,KAAK,GAAGiC,kBAAkB,CAAChI,UAAU,CAAC+F,KAAK,CAAC;MACvD,OAAO7I,qBAAqB,CAACZ,MAAM,EAAEK,GAAG,EAAEqD,UAAU,CAAC;IACvD;IACA,OAAO9C,qBAAqB,CAACZ,MAAM,EAAEK,GAAG,EAAEqD,UAAU,CAAC;EACvD;AACF,CAAC,CAAE;AACH,MAAMkK,YAAY,CAAC;EACjBzC,WAAW,CAAC+C,KAAK,EAAEC,WAAW,EAAEC,OAAO,EAAE;IACvC,IAAIZ,gBAAgB;IACpB,IAAIN,cAAc,CAACgB,KAAK,CAAC,EAAE;MACzBV,gBAAgB,GAAG9M,gBAAgB,CAAC4G,iBAAiB,EAAE,CAACmG,mBAAmB,CAACS,KAAK,CAAC,CAAC,EAAEG,GAAG,CAACrO,MAAM,CAAC;IAClG,CAAC,MAAM,IAAIqK,QAAQ,CAAC6D,KAAK,CAAC,IAAI,CAACxD,aAAa,CAACwD,KAAK,CAAC,EAAE;MACnD,IAAII,IAAI;MACR,IAAIjC,MAAM;MACV,IAAI9B,kBAAkB,CAAC2D,KAAK,CAAC,EAAE;QAC7BI,IAAI,GAAGJ,KAAK;QACZ7B,MAAM,GAAGjF,4BAA4B,CAAC8G,KAAK,CAAC;QAC5C,MAAM9C,MAAM,GAAGlE,4BAA4B,CAACgH,KAAK,CAAC;QAClD,MAAMK,iBAAiB,GAAG,CAAC3D,mBAAmB,CAACQ,MAAM,CAAC;QAChDkB,kBAAkB;QACpBlB,MAAM;QACNrG,iBAAiB,CAClB;;QACCA,iBAAiB;QACrB,IAAIyH,gBAAgB,CAACpB,MAAM,CAAC,EAAE;UAC5B,MAAM3H,eAAe,CAAChE,yCAAyC,CAAC;QAClE;QACA,IAAI+K,wBAAwB,CAAC0D,KAAK,CAAC,EAAE;UACnC,MAAMzK,eAAe,CAAC9D,iCAAiC,CAAC;QAC1D;QACA,MAAM6O,IAAI,GAAG,IAAID,iBAAiB;QAChClC,MAAM,GAAGW,iBAAiB,CAC3B;;QACDQ,gBAAgB,GAAG9M,gBAAgB,CAAC4G,iBAAiB,EAAE,CAACkH,IAAI,CAAC,EAAEH,GAAG,CAACrO,MAAM,CAAC;MAC5E,CAAC,MAAM;QACL,MAAMkC,QAAQ,GAAGgM,KAAK,CAAC/L,cAAc,CAAC;QACtC,IAAID,QAAQ,IAAI,IAAI,IAAI,OAAOA,QAAQ,KAAK,UAAU,EAAE;UACtD,MAAMuB,eAAe,CAAC7D,iCAAiC,CAAC;QAC1D;QACA,IAAIsC,QAAQ,IAAI,IAAI,EAAE;UACpB,IAAI2I,eAAe,CAACqD,KAAK,CAAC,EAAE;YAC1BI,IAAI,GAAGJ,KAAK;YACZ7B,MAAM,GAAG6B,KAAK,CAAC7B,MAAM;UACvB,CAAC,MAAM;YACLiC,IAAI,GAAG,CAAC,GAAMJ,KAAM,CAAC;YACrB7B,MAAM,GAAGiC,IAAI,CAACjC,MAAM;UACtB;QACF,CAAC,MAAM;UACLiC,IAAI,GAAKJ,KAAM;UACf7B,MAAM,GAAGD,QAAQ,CAACkC,IAAI,CAACjC,MAAM,CAAC;QAChC;QACAmB,gBAAgB,GAAG9M,gBAAgB,CAAC4G,iBAAiB,EAAE,CAAC+E,MAAM,CAAC,EAAEgC,GAAG,CAACrO,MAAM,CAAC;MAC9E;MACA,KAAK,IAAIyL,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;QAC/B+B,gBAAgB,CAAC/B,CAAC,CAAC,GAAGC,kBAAkB,CAAC4C,IAAI,CAAC7C,CAAC,CAAC,CAAC;MACnD;IACF,CAAC,MAAM;MACL+B,gBAAgB,GAAG9M,gBAAgB,CAAC4G,iBAAiB,EAAEmH,SAAS,EAAEJ,GAAG,CAACrO,MAAM,CAAC;IAC/E;IACA,MAAM0O,KAAK,GAAK,IAAIhN,WAAW,CAAC8L,gBAAgB,EAAEQ,OAAO,CAAE;IAC3D1E,mBAAmB,CAAC2D,iBAAiB,EAAEyB,KAAK,EAAElB,gBAAgB,CAAC;IAC/D,OAAOkB,KAAK;EACd;EACA,OAAO7I,IAAI,CAAC8I,GAAG,EAAE,GAAGC,IAAI,EAAE;IACxB,MAAMC,WAAW,GAAG,IAAI;IACxB,IAAI,CAAC3N,UAAU,CAAC2N,WAAW,EAAE5D,KAAK,CAAC,EAAE;MACnC,MAAMxH,eAAe;MACnBpE,kDAAkD,CACnD;;IACH;IACA,IAAIwP,WAAW,KAAKjB,YAAY,EAAE;MAChC,IAAIV,cAAc,CAACyB,GAAG,CAAC,IAAIC,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;QAC5C,MAAMmB,gBAAgB,GAAGC,mBAAmB,CAACkB,GAAG,CAAC;QACjD,MAAMG,MAAM,GAAG,IAAIxH,iBAAiB;QAClCJ,4BAA4B,CAACsG,gBAAgB,CAAC;QAC9CrG,gCAAgC,CAACqG,gBAAgB,CAAC;QAClDpG,4BAA4B,CAACoG,gBAAgB,CAAC,CAC/C;;QACD,OAAO,IAAII,YAAY;QACrB1G,4BAA4B,CAACH,wBAAwB,CAAC+H,MAAM,CAAC,CAAC,CAC/D;;MACH;MACA,IAAIF,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;QACrB,OAAO,IAAIuB,YAAY;QACrB1G,4BAA4B;QAC1BM,eAAe,CAACmH,GAAG,EAAEjD,kBAAkB,CAAC,CACzC,CACF;;;MACH;MACA,MAAMqD,OAAO,GAAGH,IAAI,CAAC,CAAC,CAAC;MACvB,MAAM3O,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;MACvB,OAAO,IAAIhB,YAAY;MACrB1G,4BAA4B;MAC1BM,eAAe,CAACmH,GAAG,EAAE,UAAUK,GAAG,EAAE,GAAG9O,IAAI,EAAE;QAC3C,OAAOwL,kBAAkB;QACvBvL,YAAY,CAAC4O,OAAO,EAAE,IAAI,EAAE,CAACC,GAAG,EAAE,GAAGrF,YAAY,CAACzJ,IAAI,CAAC,CAAC,CAAC,CAC1D;;MACH,CAAC,EAAED,OAAO,CAAC,CACZ,CACF;;;IACH;IACA,IAAIqO,IAAI;IACR,IAAIjC,MAAM;IACV,MAAMnK,QAAQ,GAAGyM,GAAG,CAACxM,cAAc,CAAC;IACpC,IAAID,QAAQ,IAAI,IAAI,IAAI,OAAOA,QAAQ,KAAK,UAAU,EAAE;MACtD,MAAMuB,eAAe,CAAC7D,iCAAiC,CAAC;IAC1D;IACA,IAAIsC,QAAQ,IAAI,IAAI,EAAE;MACpB,IAAI2I,eAAe,CAAC8D,GAAG,CAAC,EAAE;QACxBL,IAAI,GAAGK,GAAG;QACVtC,MAAM,GAAGsC,GAAG,CAACtC,MAAM;MACrB,CAAC,MAAM,IAAIvB,0BAA0B,CAAC6D,GAAG,CAAC,EAAE;QAC1CL,IAAI,GAAGK,GAAG;QACVtC,MAAM,GAAGjF,4BAA4B,CAACuH,GAAG,CAAC;MAC5C,CAAC,MAAM;QACLL,IAAI,GAAG,CAAC,GAAGK,GAAG,CAAC;QACftC,MAAM,GAAGiC,IAAI,CAACjC,MAAM;MACtB;IACF,CAAC,MAAM;MACL,IAAIsC,GAAG,IAAI,IAAI,EAAE;QACf,MAAMlL,eAAe;QACnB/D,0CAA0C,CAC3C;;MACH;MACA4O,IAAI,GAAG3L,YAAY,CAACgM,GAAG,CAAC;MACxBtC,MAAM,GAAGD,QAAQ,CAACkC,IAAI,CAACjC,MAAM,CAAC;IAChC;IACA,MAAMzC,KAAK,GAAG,IAAIiF,WAAW,CAACxC,MAAM,CAAC;IACrC,IAAIuC,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;MACrB,KAAK,IAAIZ,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;QAC/B7B,KAAK,CAAC6B,CAAC,CAAC,GAAK6C,IAAI,CAAC7C,CAAC,CAAE;MACvB;IACF,CAAC,MAAM;MACL,MAAMsD,OAAO,GAAGH,IAAI,CAAC,CAAC,CAAC;MACvB,MAAM3O,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;MACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;QAC/B7B,KAAK,CAAC6B,CAAC,CAAC,GAAGtL,YAAY,CAAC4O,OAAO,EAAE9O,OAAO,EAAE,CAACqO,IAAI,CAAC7C,CAAC,CAAC,EAAEA,CAAC,CAAC,CAAC;MACzD;IACF;IACA,OAAO7B,KAAK;EACd;EACA,OAAOqF,EAAE,CAAC,GAAGC,KAAK,EAAE;IAClB,MAAML,WAAW,GAAG,IAAI;IACxB,IAAI,CAAC3N,UAAU,CAAC2N,WAAW,EAAE5D,KAAK,CAAC,EAAE;MACnC,MAAMxH,eAAe;MACnBpE,kDAAkD,CACnD;;IACH;IACA,MAAMgN,MAAM,GAAG6C,KAAK,CAAC7C,MAAM;IAC3B,IAAIwC,WAAW,KAAKjB,YAAY,EAAE;MAChC,MAAMc,KAAK,GAAG,IAAId,YAAY,CAACvB,MAAM,CAAC;MACtC,MAAMmB,gBAAgB,GAAGC,mBAAmB,CAACiB,KAAK,CAAC;MACnD,KAAK,IAAIjD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;QAC/B+B,gBAAgB,CAAC/B,CAAC,CAAC,GAAGC,kBAAkB,CAACwD,KAAK,CAACzD,CAAC,CAAC,CAAC;MACpD;MACA,OAAOiD,KAAK;IACd;IACA,MAAM9E,KAAK,GAAG,IAAIiF,WAAW,CAACxC,MAAM,CAAC;IACrC,KAAK,IAAIZ,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B7B,KAAK,CAAC6B,CAAC,CAAC,GAAGyD,KAAK,CAACzD,CAAC,CAAC;IACrB;IACA,OAAO7B,KAAK;EACd;EACA3D,IAAI,GAAG;IACLkH,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,OAAOzH,uBAAuB,CAACwH,gBAAgB,CAAC;EAClD;EACArH,MAAM,GAAG;IACPgH,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,OAAOtD,IAAI,CAAE,aAAa;MACxB,KAAK,MAAM6E,GAAG,IAAI9I,yBAAyB,CAACsH,gBAAgB,CAAC,EAAE;QAC7D,MAAMvB,eAAe,CAAC+C,GAAG,CAAC;MAC5B;IACF,CAAC,EAAG,CAAC;EACP;EACA3I,OAAO,GAAG;IACR8G,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,OAAOtD,IAAI,CAAE,aAAa;MACxB,KAAK,MAAM,CAACsB,CAAC,EAAEuD,GAAG,CAAC,IAAI5I,0BAA0B,CAACoH,gBAAgB,CAAC,EAAE;QACnE,MAAQ,CAAC/B,CAAC,EAAEQ,eAAe,CAAC+C,GAAG,CAAC,CAAE;MACpC;IACF,CAAC,EAAG,CAAC;EACP;EACAG,EAAE,CAACC,KAAK,EAAE;IACRjC,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAM6B,aAAa,GAAGlD,mBAAmB,CAACiD,KAAK,CAAC;IAChD,MAAME,CAAC,GAAGD,aAAa,IAAI,CAAC,GAAGA,aAAa,GAAGhD,MAAM,GAAGgD,aAAa;IACrE,IAAIC,CAAC,GAAG,CAAC,IAAIA,CAAC,IAAIjD,MAAM,EAAE;MACxB;IACF;IACA,OAAOJ,eAAe,CAACuB,gBAAgB,CAAC8B,CAAC,CAAC,CAAC;EAC7C;EACAC,GAAG,CAACC,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACrBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,MAAMC,WAAW,GAAGvC,kBAAkB,CAACkB,gBAAgB,EAAEI,YAAY,CAAC;IACtE,IAAIiB,WAAW,KAAKjB,YAAY,EAAE;MAChC,MAAMc,KAAK,GAAG,IAAId,YAAY,CAACvB,MAAM,CAAC;MACtC,MAAMzC,KAAK,GAAG6D,mBAAmB,CAACiB,KAAK,CAAC;MACxC,KAAK,IAAIjD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;QAC/B,MAAMuD,GAAG,GAAG/C,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;QAChD7B,KAAK,CAAC6B,CAAC,CAAC,GAAGC,kBAAkB;QAC3BvL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAAC+O,GAAG,EAAEvD,CAAC,EAAE,IAAI,CAAC,CAAC,CAChD;;MACH;MACA,OAAOiD,KAAK;IACd;IACA,MAAM9E,KAAK,GAAG,IAAIiF,WAAW,CAACxC,MAAM,CAAC;IACrCe,uBAAuB,CAACxD,KAAK,EAAEyC,MAAM,CAAC;IACtC,KAAK,IAAIZ,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B,MAAMuD,GAAG,GAAG/C,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAChD7B,KAAK,CAAC6B,CAAC,CAAC,GAAGtL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAAC+O,GAAG,EAAEvD,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5D;IACA,OAAS7B,KAAK;EAChB;EACA6F,MAAM,CAACD,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACxBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,MAAMc,IAAI,GAAG,EAAE;IACf,KAAK,IAAIjE,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B,MAAMuD,GAAG,GAAG/C,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAChD,IAAItL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAAC+O,GAAG,EAAEvD,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;QACnDnH,kBAAkB,CAACoL,IAAI,EAAEV,GAAG,CAAC;MAC/B;IACF;IACA,MAAMH,WAAW,GAAGvC,kBAAkB,CAACkB,gBAAgB,EAAEI,YAAY,CAAC;IACtE,MAAMhE,KAAK,GAAG,IAAIiF,WAAW,CAACa,IAAI,CAAC;IACnCtC,uBAAuB,CAACxD,KAAK,CAAC;IAC9B,OAASA,KAAK;EAChB;EACA+F,MAAM,CAACH,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACxBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,IAAInB,MAAM,KAAK,CAAC,IAAIuC,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;MACrC,MAAM5I,eAAe,CAAC5D,2CAA2C,CAAC;IACpE;IACA,IAAI+P,WAAW,EAAEC,KAAK;IACtB,IAAIjB,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;MACrBuD,WAAW,GAAG3D,eAAe,CAACuB,gBAAgB,CAAC,CAAC,CAAC,CAAC;MAClDqC,KAAK,GAAG,CAAC;IACX,CAAC,MAAM;MACLD,WAAW,GAAGhB,IAAI,CAAC,CAAC,CAAC;MACrBiB,KAAK,GAAG,CAAC;IACX;IACA,KAAK,IAAIpE,CAAC,GAAGoE,KAAK,EAAEpE,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MACnCmE,WAAW,GAAGJ,QAAQ;MACpBI,WAAW;MACX3D,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MACpCA,CAAC;MACD,IAAI,CACL;;IACH;IACA,OAAOmE,WAAW;EACpB;EACAE,WAAW,CAACN,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IAC7BzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,IAAInB,MAAM,KAAK,CAAC,IAAIuC,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;MACrC,MAAM5I,eAAe,CAAC5D,2CAA2C,CAAC;IACpE;IACA,IAAI+P,WAAW,EAAEC,KAAK;IACtB,IAAIjB,IAAI,CAACvC,MAAM,KAAK,CAAC,EAAE;MACrBuD,WAAW,GAAG3D,eAAe,CAACuB,gBAAgB,CAACnB,MAAM,GAAG,CAAC,CAAC,CAAC;MAC3DwD,KAAK,GAAGxD,MAAM,GAAG,CAAC;IACpB,CAAC,MAAM;MACLuD,WAAW,GAAGhB,IAAI,CAAC,CAAC,CAAC;MACrBiB,KAAK,GAAGxD,MAAM,GAAG,CAAC;IACpB;IACA,KAAK,IAAIZ,CAAC,GAAGoE,KAAK,EAAEpE,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;MAC/BmE,WAAW,GAAGJ,QAAQ;MACpBI,WAAW;MACX3D,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MACpCA,CAAC;MACD,IAAI,CACL;;IACH;IACA,OAAOmE,WAAW;EACpB;EACAG,OAAO,CAACP,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACzBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/BtL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE;MAC9BgM,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MACpCA,CAAC;MACD,IAAI,CACL,CAAC;;IACJ;EACF;EACAuE,IAAI,CAACR,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACtBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B,MAAMhC,KAAK,GAAGwC,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAClD,IAAItL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAACwJ,KAAK,EAAEgC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;QACrD,OAAOhC,KAAK;MACd;IACF;EACF;EACAwG,SAAS,CAACT,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IAC3BzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B,MAAMhC,KAAK,GAAGwC,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAClD,IAAItL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAACwJ,KAAK,EAAEgC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;QACrD,OAAOA,CAAC;MACV;IACF;IACA,OAAO,CAAC,CAAC;EACX;EACAyE,QAAQ,CAACV,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IAC1BzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAGY,MAAM,GAAG,CAAC,EAAEZ,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;MACpC,MAAMhC,KAAK,GAAGwC,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAClD,IAAItL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAACwJ,KAAK,EAAEgC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;QACrD,OAAOhC,KAAK;MACd;IACF;EACF;EACA0G,aAAa,CAACX,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IAC/BzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAGY,MAAM,GAAG,CAAC,EAAEZ,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;MACpC,MAAMhC,KAAK,GAAGwC,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAClD,IAAItL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE,CAACwJ,KAAK,EAAEgC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE;QACrD,OAAOA,CAAC;MACV;IACF;IACA,OAAO,CAAC,CAAC;EACX;EACA2E,KAAK,CAACZ,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACvBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B;MACE,CAACtL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE;MAC/BgM,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MACpCA,CAAC;MACD,IAAI,CACL,CAAC;;MACF;QACA,OAAO,KAAK;MACd;IACF;IACA,OAAO,IAAI;EACb;EACA4E,IAAI,CAACb,QAAQ,EAAE,GAAGZ,IAAI,EAAE;IACtBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMvN,OAAO,GAAG2O,IAAI,CAAC,CAAC,CAAC;IACvB,KAAK,IAAInD,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAC/B;MACEtL,YAAY,CAACqP,QAAQ,EAAEvP,OAAO,EAAE;MAC9BgM,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MACpCA,CAAC;MACD,IAAI,CACL,CAAC;;MACF;QACA,OAAO,IAAI;MACb;IACF;IACA,OAAO,KAAK;EACd;EACApK,GAAG,CAAC6M,KAAK,EAAE,GAAGU,IAAI,EAAE;IAClBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAM6C,YAAY,GAAGnE,mBAAmB,CAACyC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjD,IAAI0B,YAAY,GAAG,CAAC,EAAE;MACpB,MAAM7H,gBAAgB,CAAC3I,uBAAuB,CAAC;IACjD;IACA,IAAIoO,KAAK,IAAI,IAAI,EAAE;MACjB,MAAMzK,eAAe;MACnB/D,0CAA0C,CAC3C;;IACH;IACA,IAAI8K,wBAAwB,CAAC0D,KAAK,CAAC,EAAE;MACnC,MAAMzK,eAAe;MACnB9D,iCAAiC,CAClC;;IACH;IACA,IAAIuN,cAAc,CAACgB,KAAK,CAAC,EAAE;MACzB,OAAO5H,sBAAsB;MAC3BmH,mBAAmB,CAAC,IAAI,CAAC;MACzBA,mBAAmB,CAACS,KAAK,CAAC;MAC1BoC,YAAY,CACb;;IACH;IACA,IAAI/F,kBAAkB,CAAC2D,KAAK,CAAC,EAAE;MAC7B,MAAM9C,MAAM,GAAGlE,4BAA4B,CAACgH,KAAK,CAAC;MAClD,IAAI1B,gBAAgB,CAACpB,MAAM,CAAC,EAAE;QAC5B,MAAM3H,eAAe,CAAChE,yCAAyC,CAAC;MAClE;IACF;IACA,MAAM8Q,YAAY,GAAGnJ,4BAA4B,CAACoG,gBAAgB,CAAC;IACnE,MAAMmB,GAAG,GAAGhM,YAAY,CAACuL,KAAK,CAAC;IAC/B,MAAMsC,SAAS,GAAGpE,QAAQ,CAACuC,GAAG,CAACtC,MAAM,CAAC;IACtC,IAAIiE,YAAY,KAAKG,QAAQ,IAAID,SAAS,GAAGF,YAAY,GAAGC,YAAY,EAAE;MACxE,MAAM9H,gBAAgB,CAAC3I,uBAAuB,CAAC;IACjD;IACA,KAAK,IAAI2L,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG+E,SAAS,EAAE,EAAE/E,CAAC,EAAE;MAClC+B,gBAAgB,CAAC/B,CAAC,GAAG6E,YAAY,CAAC,GAAG5E,kBAAkB,CAACiD,GAAG,CAAClD,CAAC,CAAC,CAAC;IACjE;EACF;EACAjF,OAAO,GAAG;IACR2G,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClDlH,0BAA0B,CAACiH,gBAAgB,CAAC;IAC5C,OAAO,IAAI;EACb;EACA9G,IAAI,CAAC+C,KAAK,EAAE,GAAGmF,IAAI,EAAE;IACnBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClDhH,uBAAuB;IACrB+G,gBAAgB;IAChB9B,kBAAkB,CAACjC,KAAK,CAAC;IACzB,GAAGE,YAAY,CAACiF,IAAI,CAAC,CACtB;;IACD,OAAO,IAAI;EACb;EACAhI,UAAU,CAAC5G,MAAM,EAAE6P,KAAK,EAAE,GAAGjB,IAAI,EAAE;IACjCzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD9G,6BAA6B,CAAC6G,gBAAgB,EAAExN,MAAM,EAAE6P,KAAK,EAAE,GAAGlG,YAAY,CAACiF,IAAI,CAAC,CAAC;IACrF,OAAO,IAAI;EACb;EACA9H,IAAI,CAAC4J,SAAS,EAAE;IACdvD,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMkD,WAAW,GAAGD,SAAS,KAAK/M,SAAS,GAAG+M,SAAS,GAAGjE,cAAc;IACxE5F,uBAAuB,CAAC2G,gBAAgB,EAAE,CAACd,CAAC,EAAEC,CAAC,KAAK;MAClD,OAAOgE,WAAW,CAAC1E,eAAe,CAACS,CAAC,CAAC,EAAET,eAAe,CAACU,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC;IACF,OAAO,IAAI;EACb;EACAtH,KAAK,CAACwK,KAAK,EAAEe,GAAG,EAAE;IAChBzD,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMoB,WAAW,GAAGvC,kBAAkB,CAACkB,gBAAgB,EAAEI,YAAY,CAAC;IACtE,IAAIiB,WAAW,KAAKjB,YAAY,EAAE;MAChC,MAAMkB,MAAM,GAAG,IAAIxH,iBAAiB;MAClCJ,4BAA4B,CAACsG,gBAAgB,CAAC;MAC9CrG,gCAAgC,CAACqG,gBAAgB,CAAC;MAClDpG,4BAA4B,CAACoG,gBAAgB,CAAC,CAC/C;;MACD,OAAO,IAAII,YAAY;MACrB1G,4BAA4B;MAC1BH,wBAAwB,CAAC+H,MAAM,EAAEe,KAAK,EAAEe,GAAG,CAAC,CAC7C,CACF;;;IACH;IACA,MAAMvE,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,MAAMqD,aAAa,GAAG1E,mBAAmB,CAAC0D,KAAK,CAAC;IAChD,MAAMiB,WAAW,GAAGF,GAAG,KAAKjN,SAAS,GAAG0I,MAAM,GAAGF,mBAAmB,CAACyE,GAAG,CAAC;IACzE,IAAItB,CAAC;IACL,IAAIuB,aAAa,KAAK,CAACJ,QAAQ,EAAE;MAC/BnB,CAAC,GAAG,CAAC;IACP,CAAC,MAAM,IAAIuB,aAAa,GAAG,CAAC,EAAE;MAC5BvB,CAAC,GAAGjD,MAAM,GAAGwE,aAAa,GAAG,CAAC,GAAGxE,MAAM,GAAGwE,aAAa,GAAG,CAAC;IAC7D,CAAC,MAAM;MACLvB,CAAC,GAAGjD,MAAM,GAAGwE,aAAa,GAAGxE,MAAM,GAAGwE,aAAa;IACrD;IACA,IAAIE,KAAK;IACT,IAAID,WAAW,KAAK,CAACL,QAAQ,EAAE;MAC7BM,KAAK,GAAG,CAAC;IACX,CAAC,MAAM,IAAID,WAAW,GAAG,CAAC,EAAE;MAC1BC,KAAK,GAAG1E,MAAM,GAAGyE,WAAW,GAAG,CAAC,GAAGzE,MAAM,GAAGyE,WAAW,GAAG,CAAC;IAC7D,CAAC,MAAM;MACLC,KAAK,GAAG1E,MAAM,GAAGyE,WAAW,GAAGzE,MAAM,GAAGyE,WAAW;IACrD;IACA,MAAMzD,KAAK,GAAG0D,KAAK,GAAGzB,CAAC,GAAG,CAAC,GAAGyB,KAAK,GAAGzB,CAAC,GAAG,CAAC;IAC3C,MAAM1F,KAAK,GAAG,IAAIiF,WAAW,CAACxB,KAAK,CAAC;IACpCD,uBAAuB,CAACxD,KAAK,EAAEyD,KAAK,CAAC;IACrC,IAAIA,KAAK,KAAK,CAAC,EAAE;MACf,OAAOzD,KAAK;IACd;IACA,MAAMwB,MAAM,GAAGlE,4BAA4B,CAACsG,gBAAgB,CAAC;IAC7D,IAAIhB,gBAAgB,CAACpB,MAAM,CAAC,EAAE;MAC5B,MAAM3H,eAAe,CAAChE,yCAAyC,CAAC;IAClE;IACA,IAAIuR,CAAC,GAAG,CAAC;IACT,OAAO1B,CAAC,GAAGyB,KAAK,EAAE;MAChBnH,KAAK,CAACoH,CAAC,CAAC,GAAG/E,eAAe,CAACuB,gBAAgB,CAAC8B,CAAC,CAAC,CAAC;MAC/C,EAAEA,CAAC;MACH,EAAE0B,CAAC;IACL;IACA,OAASpH,KAAK;EAChB;EACA3C,QAAQ,CAACgK,KAAK,EAAEL,GAAG,EAAE;IACnBzD,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMoB,WAAW,GAAGvC,kBAAkB,CAACkB,gBAAgB,EAAEI,YAAY,CAAC;IACtE,MAAMkB,MAAM,GAAG,IAAIxH,iBAAiB;IAClCJ,4BAA4B,CAACsG,gBAAgB,CAAC;IAC9CrG,gCAAgC,CAACqG,gBAAgB,CAAC;IAClDpG,4BAA4B,CAACoG,gBAAgB,CAAC,CAC/C;;IACD,MAAM0D,cAAc,GAAGlK,2BAA2B,CAAC8H,MAAM,EAAEmC,KAAK,EAAEL,GAAG,CAAC;IACtE,MAAMhH,KAAK,GAAG,IAAIiF,WAAW;IAC3B3H,4BAA4B,CAACgK,cAAc,CAAC;IAC5C/J,gCAAgC,CAAC+J,cAAc,CAAC;IAChD9J,4BAA4B,CAAC8J,cAAc,CAAC,CAC7C;;IACD9D,uBAAuB,CAACxD,KAAK,CAAC;IAC9B,OAASA,KAAK;EAChB;EACAuH,OAAO,CAACC,OAAO,EAAE,GAAGxC,IAAI,EAAE;IACxBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,IAAI3H,IAAI,GAAGsG,mBAAmB,CAACyC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI/I,IAAI,KAAK4K,QAAQ,EAAE;MACrB,OAAO,CAAC,CAAC;IACX;IACA,IAAI5K,IAAI,GAAG,CAAC,EAAE;MACZA,IAAI,IAAIwG,MAAM;MACd,IAAIxG,IAAI,GAAG,CAAC,EAAE;QACZA,IAAI,GAAG,CAAC;MACV;IACF;IACA,KAAK,IAAI4F,CAAC,GAAG5F,IAAI,EAAE4F,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAClC;MACE7H,YAAY,CAAC4J,gBAAgB,EAAE/B,CAAC,CAAC;MACjCQ,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC,KAAK2F,OAAO;MAChD;QACA,OAAO3F,CAAC;MACV;IACF;IACA,OAAO,CAAC,CAAC;EACX;EACA4F,WAAW,CAACD,OAAO,EAAE,GAAGxC,IAAI,EAAE;IAC5BzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,IAAI3H,IAAI,GAAG+I,IAAI,CAACvC,MAAM,IAAI,CAAC,GAAGF,mBAAmB,CAACyC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAGvC,MAAM,GAAG,CAAC;IACvE,IAAIxG,IAAI,KAAK,CAAC4K,QAAQ,EAAE;MACtB,OAAO,CAAC,CAAC;IACX;IACA,IAAI5K,IAAI,IAAI,CAAC,EAAE;MACbA,IAAI,GAAGA,IAAI,GAAGwG,MAAM,GAAG,CAAC,GAAGxG,IAAI,GAAGwG,MAAM,GAAG,CAAC;IAC9C,CAAC,MAAM;MACLxG,IAAI,IAAIwG,MAAM;IAChB;IACA,KAAK,IAAIZ,CAAC,GAAG5F,IAAI,EAAE4F,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;MAC9B;MACE7H,YAAY,CAAC4J,gBAAgB,EAAE/B,CAAC,CAAC;MACjCQ,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC,KAAK2F,OAAO;MAChD;QACA,OAAO3F,CAAC;MACV;IACF;IACA,OAAO,CAAC,CAAC;EACX;EACA6F,QAAQ,CAACF,OAAO,EAAE,GAAGxC,IAAI,EAAE;IACzBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAMpB,MAAM,GAAGjF,4BAA4B,CAACoG,gBAAgB,CAAC;IAC7D,IAAI3H,IAAI,GAAGsG,mBAAmB,CAACyC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI/I,IAAI,KAAK4K,QAAQ,EAAE;MACrB,OAAO,KAAK;IACd;IACA,IAAI5K,IAAI,GAAG,CAAC,EAAE;MACZA,IAAI,IAAIwG,MAAM;MACd,IAAIxG,IAAI,GAAG,CAAC,EAAE;QACZA,IAAI,GAAG,CAAC;MACV;IACF;IACA,MAAM9D,KAAK,GAAGC,WAAW,CAACoP,OAAO,CAAC;IAClC,KAAK,IAAI3F,CAAC,GAAG5F,IAAI,EAAE4F,CAAC,GAAGY,MAAM,EAAE,EAAEZ,CAAC,EAAE;MAClC,MAAMhC,KAAK,GAAGwC,eAAe,CAACuB,gBAAgB,CAAC/B,CAAC,CAAC,CAAC;MAClD,IAAI1J,KAAK,IAAIC,WAAW,CAACyH,KAAK,CAAC,EAAE;QAC/B,OAAO,IAAI;MACb;MACA,IAAIA,KAAK,KAAK2H,OAAO,EAAE;QACrB,OAAO,IAAI;MACb;IACF;IACA,OAAO,KAAK;EACd;EACA/M,IAAI,CAACkN,SAAS,EAAE;IACdpE,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAM7D,KAAK,GAAGkE,WAAW,CAACN,gBAAgB,CAAC;IAC3C,OAAOpJ,kBAAkB,CAACwF,KAAK,EAAE2H,SAAS,CAAC;EAC7C;EACA9M,cAAc,CAAC,GAAGmK,IAAI,EAAE;IACtBzB,kBAAkB,CAAC,IAAI,CAAC;IACxB,MAAMK,gBAAgB,GAAGC,mBAAmB,CAAC,IAAI,CAAC;IAClD,MAAM7D,KAAK,GAAGkE,WAAW,CAACN,gBAAgB,CAAC;IAC3C,OAAOhJ,4BAA4B,CAACoF,KAAK,EAAE,GAAGD,YAAY,CAACiF,IAAI,CAAC,CAAC;EACnE;EACA,KAAKrM,iBAAiB,IAAI;IACxB,IAAI2K,cAAc,CAAC,IAAI,CAAC,EAAE;MACxB,OAAS,cAAc;IACzB;EACF;AACF;AACAnK,oBAAoB,CAAC6K,YAAY,EAAE,mBAAmB,EAAE;EACtDnE,KAAK,EAAEuD;AACT,CAAC,CAAC;AACFjK,oBAAoB,CAAC6K,YAAY,EAAE3C,KAAK,EAAE,CAAC,CAAC,CAAC;AAC7CzJ,qBAAqB,CAACoM,YAAY,EAAElI,UAAU,CAAC;AAC/C,MAAM8L,qBAAqB,GAAG5D,YAAY,CAACvK,SAAS;AACpDN,oBAAoB,CAACyO,qBAAqB,EAAE,mBAAmB,EAAE;EAC/D/H,KAAK,EAAEuD;AACT,CAAC,CAAC;AACFjK,oBAAoB,CAACyO,qBAAqB,EAAErP,cAAc,EAAE;EAC1DsH,KAAK,EAAE+H,qBAAqB,CAACrL,MAAM;EACnC8D,QAAQ,EAAE,IAAI;EACdC,YAAY,EAAE;AAChB,CAAC,CAAC;AACF1I,qBAAqB,CAACgQ,qBAAqB,EAAE1L,mBAAmB,CAAC;;AAEjE,SAAS2L,YAAY,CAACzR,MAAM,EAAE;EAC5B,OAAOuK,kBAAkB,CAACvK,MAAM,CAAC,IAAIkN,cAAc,CAAClN,MAAM,CAAC;AAC7D;;AAEA,SAAS0R,UAAU,CAACC,QAAQ,EAAE9D,UAAU,EAAE,GAAGe,IAAI,EAAE;EACjD,OAAO3C,eAAe;EACpB7D,0BAA0B,CAACuJ,QAAQ,EAAE9D,UAAU,EAAE,GAAGlE,YAAY,CAACiF,IAAI,CAAC,CAAC,CACxE;;AACH;AACA,SAASgD,UAAU,CAACD,QAAQ,EAAE9D,UAAU,EAAEpE,KAAK,EAAE,GAAGmF,IAAI,EAAE;EACxD,OAAOtG,0BAA0B;EAC/BqJ,QAAQ;EACR9D,UAAU;EACVnC,kBAAkB,CAACjC,KAAK,CAAC;EACzB,GAAGE,YAAY,CAACiF,IAAI,CAAC,CACtB;;AACH;;AAEA,SAASiD,OAAO,CAACnF,CAAC,EAAE;EAClB,MAAM1B,MAAM,GAAG,CAAC0B,CAAC;EACjB,IAAI,CAAC5K,cAAc,CAACkJ,MAAM,CAAC,IAAIA,MAAM,KAAK,CAAC,EAAE;IAC3C,OAAOA,MAAM;EACf;EACA,MAAM8G,GAAG,GAAGpG,kBAAkB,CAACV,MAAM,CAAC;EACtC,OAAOiB,eAAe,CAAC6F,GAAG,CAAC;AAC7B;;AAEA,SAASlE,YAAY,EAAE8D,UAAU,EAAEG,OAAO,EAAE3E,cAAc,EAAEuE,YAAY,EAAEG,UAAU"} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/README.md b/testing/web-platform/mozilla/tests/webgpu/resources/README.md
new file mode 100644
index 0000000000..c918eb373c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/README.md
@@ -0,0 +1,2 @@
+Always use `getResourcePath()` to get the appropriate path to these resources depending
+on the context (WPT, standalone, worker, etc.)
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt2020.vp9.webm b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt2020.vp9.webm
new file mode 100644
index 0000000000..91850cdbea
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt2020.vp9.webm
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt601.vp9.webm b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt601.vp9.webm
new file mode 100644
index 0000000000..d90e1911c6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt601.vp9.webm
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt709.vp9.webm b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt709.vp9.webm
new file mode 100644
index 0000000000..1bb70ef572
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.bt709.vp9.webm
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.mp4 b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.mp4
new file mode 100644
index 0000000000..4bd6d59658
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.mp4
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.theora.ogv b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.theora.ogv
new file mode 100644
index 0000000000..1543915a10
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.theora.ogv
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/red-green.webmvp8.webm b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.webmvp8.webm
new file mode 100644
index 0000000000..fde59a18b4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/red-green.webmvp8.webm
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/resources/webgpu.png b/testing/web-platform/mozilla/tests/webgpu/resources/webgpu.png
new file mode 100644
index 0000000000..eec0d6eb90
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/resources/webgpu.png
Binary files differ
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapter.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapter.spec.js
new file mode 100644
index 0000000000..62608876dd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapter.spec.js
@@ -0,0 +1,122 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for GPU.requestAdapter.
+
+Test all possible options to requestAdapter.
+default, low-power, and high performance should all always return adapters.
+forceFallbackAdapter may or may not return an adapter.
+
+GPU.requestAdapter can technically return null for any reason
+but we need test functionality so the test requires an adapter except
+when forceFallbackAdapter is true.
+
+The test runs simple compute shader is run that fills a buffer with consecutive
+values and then checks the result to test the adapter for basic functionality.
+`;
+import { Fixture } from '../../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { getGPU } from '../../../../common/util/navigator_gpu.js';
+import { assert, objectEquals, iterRange } from '../../../../common/util/util.js';
+
+export const g = makeTestGroup(Fixture);
+
+const powerPreferenceModes = [undefined, 'low-power', 'high-performance'];
+
+const forceFallbackOptions = [undefined, false, true];
+
+async function testAdapter(adapter) {
+ assert(adapter !== null, 'Failed to get adapter.');
+ const device = await adapter.requestDevice();
+
+ assert(device !== null, 'Failed to get device.');
+
+ const kOffset = 1230000;
+ const pipeline = device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: device.createShaderModule({
+ code: `
+ struct Buffer { data: array<u32>, };
+
+ @group(0) @binding(0) var<storage, read_write> buffer: Buffer;
+ @compute @workgroup_size(1u) fn main(
+ @builtin(global_invocation_id) id: vec3<u32>) {
+ buffer.data[id.x] = id.x + ${kOffset}u;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const kNumElements = 64;
+ const kBufferSize = kNumElements * 4;
+ const buffer = device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ const resultBuffer = device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
+ });
+
+ const bindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer } }],
+ });
+
+ const encoder = device.createCommandEncoder();
+
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(kNumElements);
+ pass.end();
+
+ encoder.copyBufferToBuffer(buffer, 0, resultBuffer, 0, kBufferSize);
+
+ device.queue.submit([encoder.finish()]);
+
+ const expected = new Uint32Array([...iterRange(kNumElements, x => x + kOffset)]);
+
+ await resultBuffer.mapAsync(GPUMapMode.READ);
+ const actual = new Uint32Array(resultBuffer.getMappedRange());
+
+ assert(objectEquals(actual, expected), 'compute pipeline ran');
+
+ resultBuffer.destroy();
+ buffer.destroy();
+ device.destroy();
+}
+
+g.test('requestAdapter')
+ .desc(`request adapter with all possible options and check for basic functionality`)
+ .params(u =>
+ u
+ .combine('powerPreference', powerPreferenceModes)
+ .combine('forceFallbackAdapter', forceFallbackOptions)
+ )
+ .fn(async t => {
+ const { powerPreference, forceFallbackAdapter } = t.params;
+ const adapter = await getGPU().requestAdapter({
+ ...(powerPreference !== undefined && { powerPreference }),
+ ...(forceFallbackAdapter !== undefined && { forceFallbackAdapter }),
+ });
+
+ // failing to create an adapter when forceFallbackAdapter is true is ok.
+ if (forceFallbackAdapter && !adapter) {
+ t.skip('No adapter available');
+ return;
+ }
+
+ await testAdapter(adapter);
+ });
+
+g.test('requestAdapter_no_parameters')
+ .desc(`request adapter with no parameters`)
+ .fn(async () => {
+ const adapter = await getGPU().requestAdapter();
+ await testAdapter(adapter);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapterInfo.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapterInfo.spec.js
new file mode 100644
index 0000000000..62feb44852
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestAdapterInfo.spec.js
@@ -0,0 +1,55 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests various ways of calling GPUAdapter.requestAdapterInfo.
+
+TODO:
+- Find a way to perform tests with and without user activation
+`;
+import { Fixture } from '../../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { getGPU } from '../../../../common/util/navigator_gpu.js';
+import { assert } from '../../../../common/util/util.js';
+
+export const g = makeTestGroup(Fixture);
+
+const normalizedIdentifierRegex = /^$|^[a-z0-9]+(-[a-z0-9]+)*$/;
+
+g.test('adapter_info')
+ .desc(
+ `
+ Test that calling requestAdapterInfo with no arguments:
+ - Returns a GPUAdapterInfo structure
+ - Every member in the structure except description is properly formatted`
+ )
+ .fn(async t => {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ const adapterInfo = await adapter.requestAdapterInfo();
+
+ t.expect(
+ normalizedIdentifierRegex.test(adapterInfo.vendor),
+ 'adapterInfo.vendor should be a normalized identifier'
+ );
+
+ t.expect(
+ normalizedIdentifierRegex.test(adapterInfo.architecture),
+ 'adapterInfo.architecture should be a normalized identifier'
+ );
+
+ t.expect(
+ normalizedIdentifierRegex.test(adapterInfo.device),
+ 'adapterInfo.device should be a normalized identifier'
+ );
+ });
+
+g.test('adapter_info_with_hints')
+ .desc(
+ `
+ Test that calling requestAdapterInfo with hints:
+ - Rejects without user activation
+ - Succeed with user activation`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js
new file mode 100644
index 0000000000..f2a4c636a0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/adapter/requestDevice.spec.js
@@ -0,0 +1,274 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test GPUAdapter.requestDevice.
+
+Note tests explicitly destroy created devices so that tests don't have to wait for GC to clean up
+potentially limited native resources.
+`;
+import { Fixture } from '../../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { getGPU } from '../../../../common/util/navigator_gpu.js';
+import { assert, raceWithRejectOnTimeout } from '../../../../common/util/util.js';
+import { kFeatureNames, kLimitInfo, kLimits } from '../../../capability_info.js';
+import { clamp, isPowerOfTwo } from '../../../util/math.js';
+
+export const g = makeTestGroup(Fixture);
+
+g.test('default')
+ .desc(
+ `
+ Test requesting the device with a variation of default paramters.
+ - No features listed in default device
+ - Default limits`
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('args', [[], [undefined], [{}], [{ requiredFeatures: [], requiredLimits: {} }]])
+ )
+ .fn(async t => {
+ const { args } = t.params;
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+ const device = await adapter.requestDevice(...args);
+ assert(device !== null);
+
+ // Default device should have no features.
+ t.expect(device.features.size === 0, 'Default device should not have any features');
+ // All limits should be defaults.
+ for (const limit of kLimits) {
+ t.expect(
+ device.limits[limit] === kLimitInfo[limit].default,
+ `Expected ${limit} == default: ${device.limits[limit]} != ${kLimitInfo[limit].default}`
+ );
+ }
+
+ device.destroy();
+ });
+
+g.test('invalid')
+ .desc(
+ `
+ Test that requesting device on an invalid adapter resolves with lost device.
+ - Induce invalid adapter via a device lost from a device.destroy()`
+ )
+ .fn(async t => {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ {
+ // Request a device and destroy it immediately afterwards.
+ const device = await adapter.requestDevice();
+ assert(device !== null);
+ device.destroy();
+ const lostInfo = await device.lost;
+ t.expect(lostInfo.reason === 'destroyed');
+ }
+
+ // The adapter should now be invalid since a device was lost. Requesting another device should
+ // return an already lost device.
+ const kTimeoutMS = 1000;
+ const device = await adapter.requestDevice();
+ const lost = await raceWithRejectOnTimeout(device.lost, kTimeoutMS, 'device was not lost');
+ t.expect(lost.reason === undefined);
+ });
+
+g.test('features,unknown')
+ .desc(
+ `
+ Test requesting device with an unknown feature.`
+ )
+ .fn(async t => {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ t.shouldReject('TypeError', adapter.requestDevice({ requiredFeatures: ['unknown-feature'] }));
+ });
+
+g.test('features,known')
+ .desc(
+ `
+ Test requesting device with all features.
+ - Succeeds with device supporting feature if adapter supports the feature.
+ - Rejects if the adapter does not support the feature.`
+ )
+ .params(u => u.combine('feature', kFeatureNames))
+ .fn(async t => {
+ const { feature } = t.params;
+
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ const promise = adapter.requestDevice({ requiredFeatures: [feature] });
+ if (adapter.features.has(feature)) {
+ const device = await promise;
+ t.expect(device.features.has(feature), 'Device should include the required feature');
+ } else {
+ t.shouldReject('TypeError', promise);
+ }
+ });
+
+g.test('limits,unknown')
+ .desc(
+ `
+ Test that specifying limits that aren't part of the supported limit set causes
+ requestDevice to reject.`
+ )
+ .fn(async t => {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ const requiredLimits = { unknownLimitName: 9000 };
+
+ t.shouldReject('OperationError', adapter.requestDevice({ requiredLimits }));
+ });
+
+g.test('limits,supported')
+ .desc(
+ `
+ Test that each supported limit can be specified with valid values.
+ - Tests each limit with the default values given by the spec
+ - Tests each limit with the supported values given by the adapter`
+ )
+ .params(u =>
+ u.combine('limit', kLimits).beginSubcases().combine('limitValue', ['default', 'adapter'])
+ )
+ .fn(async t => {
+ const { limit, limitValue } = t.params;
+
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ let value = -1;
+ switch (limitValue) {
+ case 'default':
+ value = kLimitInfo[limit].default;
+ break;
+ case 'adapter':
+ value = adapter.limits[limit];
+ break;
+ }
+
+ const device = await adapter.requestDevice({ requiredLimits: { [limit]: value } });
+ assert(device !== null);
+ t.expect(
+ device.limits[limit] === value,
+ 'Devices reported limit should match the required limit'
+ );
+
+ device.destroy();
+ });
+
+g.test('limit,better_than_supported')
+ .desc(
+ `
+ Test that specifying a better limit than what the adapter supports causes requestDevice to
+ reject.
+ - Tests each limit
+ - Tests requesting better limits by various amounts`
+ )
+ .params(u =>
+ u
+ .combine('limit', kLimits)
+ .beginSubcases()
+ .expandWithParams(p => {
+ switch (kLimitInfo[p.limit].class) {
+ case 'maximum':
+ return [
+ { mul: 1, add: 1 },
+ { mul: 1, add: 100 },
+ ];
+
+ case 'alignment':
+ return [
+ { mul: 1, add: -1 },
+ { mul: 1 / 2, add: 0 },
+ { mul: 1 / 1024, add: 0 },
+ ];
+ }
+ })
+ )
+ .fn(async t => {
+ const { limit, mul, add } = t.params;
+
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ const value = adapter.limits[limit] * mul + add;
+ const requiredLimits = {
+ [limit]: clamp(value, { min: 0, max: kLimitInfo[limit].maximumValue }),
+ };
+
+ t.shouldReject('OperationError', adapter.requestDevice({ requiredLimits }));
+ });
+
+g.test('limit,worse_than_default')
+ .desc(
+ `
+ Test that specifying a worse limit than the default values required by the spec cause the value
+ to clamp.
+ - Tests each limit
+ - Tests requesting worse limits by various amounts`
+ )
+ .params(u =>
+ u
+ .combine('limit', kLimits)
+ .beginSubcases()
+ .expandWithParams(p => {
+ switch (kLimitInfo[p.limit].class) {
+ case 'maximum':
+ return [
+ { mul: 1, add: -1 },
+ { mul: 1, add: -100 },
+ ];
+
+ case 'alignment':
+ return [
+ { mul: 1, add: 1 },
+ { mul: 2, add: 0 },
+ { mul: 1024, add: 0 },
+ ];
+ }
+ })
+ )
+ .fn(async t => {
+ const { limit, mul, add } = t.params;
+
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+
+ const value = kLimitInfo[limit].default * mul + add;
+ const requiredLimits = {
+ [limit]: clamp(value, { min: 0, max: kLimitInfo[limit].maximumValue }),
+ };
+
+ let success;
+ switch (kLimitInfo[limit].class) {
+ case 'alignment':
+ success = isPowerOfTwo(value);
+ break;
+ case 'maximum':
+ success = true;
+ break;
+ }
+
+ if (success) {
+ const device = await adapter.requestDevice({ requiredLimits });
+ assert(device !== null);
+ t.expect(
+ device.limits[limit] === kLimitInfo[limit].default,
+ 'Devices reported limit should match the default limit'
+ );
+
+ device.destroy();
+ } else {
+ t.shouldReject('OperationError', adapter.requestDevice({ requiredLimits }));
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map.spec.js
new file mode 100644
index 0000000000..63afab454e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map.spec.js
@@ -0,0 +1,491 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test the operation of buffer mapping, specifically the data contents written via
+map-write/mappedAtCreation, and the contents of buffers returned by getMappedRange on
+buffers which are mapped-read/mapped-write/mappedAtCreation.
+
+range: used for getMappedRange
+mapRegion: used for mapAsync
+
+mapRegionBoundModes is used to get mapRegion from range:
+ - default-expand: expand mapRegion to buffer bound by setting offset/size to undefined
+ - explicit-expand: expand mapRegion to buffer bound by explicitly calculating offset/size
+ - minimal: make mapRegion to be the same as range which is the minimal range to make getMappedRange input valid
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, memcpy } from '../../../../common/util/util.js';
+import { checkElementsEqual } from '../../../util/check_contents.js';
+
+import { MappingTest } from './mapping_test.js';
+
+export const g = makeTestGroup(MappingTest);
+
+const kSubcases = [
+ { size: 0, range: [] },
+ { size: 0, range: [undefined] },
+ { size: 0, range: [undefined, undefined] },
+ { size: 0, range: [0] },
+ { size: 0, range: [0, undefined] },
+ { size: 0, range: [0, 0] },
+ { size: 12, range: [] },
+ { size: 12, range: [undefined] },
+ { size: 12, range: [undefined, undefined] },
+ { size: 12, range: [0] },
+ { size: 12, range: [0, undefined] },
+ { size: 12, range: [0, 12] },
+ { size: 12, range: [0, 0] },
+ { size: 12, range: [8] },
+ { size: 12, range: [8, undefined] },
+ { size: 12, range: [8, 4] },
+ { size: 28, range: [8, 8] },
+ { size: 28, range: [8, 12] },
+ { size: 512 * 1024, range: [] },
+];
+
+function reifyMapRange(bufferSize, range) {
+ const offset = range[0] ?? 0;
+ return [offset, range[1] ?? bufferSize - offset];
+}
+
+const mapRegionBoundModes = ['default-expand', 'explicit-expand', 'minimal'];
+
+function getRegionForMap(bufferSize, range, { mapAsyncRegionLeft, mapAsyncRegionRight }) {
+ const regionLeft = mapAsyncRegionLeft === 'minimal' ? range[0] : 0;
+ const regionRight = mapAsyncRegionRight === 'minimal' ? range[0] + range[1] : bufferSize;
+ return [
+ mapAsyncRegionLeft === 'default-expand' ? undefined : regionLeft,
+ mapAsyncRegionRight === 'default-expand' ? undefined : regionRight - regionLeft,
+ ];
+}
+
+g.test('mapAsync,write')
+ .desc(
+ `Use map-write to write to various ranges of variously-sized buffers, then expectContents
+(which does copyBufferToBuffer + map-read) to ensure the contents were written.`
+ )
+ .params(u =>
+ u
+ .combine('mapAsyncRegionLeft', mapRegionBoundModes)
+ .combine('mapAsyncRegionRight', mapRegionBoundModes)
+ .beginSubcases()
+ .combineWithParams(kSubcases)
+ )
+ .fn(async t => {
+ const { size, range } = t.params;
+ const [rangeOffset, rangeSize] = reifyMapRange(size, range);
+
+ const buffer = t.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
+
+ const mapRegion = getRegionForMap(size, [rangeOffset, rangeSize], t.params);
+ await buffer.mapAsync(GPUMapMode.WRITE, ...mapRegion);
+ const arrayBuffer = buffer.getMappedRange(...range);
+ t.checkMapWrite(buffer, rangeOffset, arrayBuffer, rangeSize);
+ });
+
+g.test('mapAsync,write,unchanged_ranges_preserved')
+ .desc(
+ `Use mappedAtCreation or mapAsync to write to various ranges of variously-sized buffers, then
+use mapAsync to map a different range and zero it out. Finally use expectGPUBufferValuesEqual
+(which does copyBufferToBuffer + map-read) to verify that contents originally written outside the
+second mapped range were not altered.`
+ )
+ .params(u =>
+ u
+ .beginSubcases()
+ .combine('mappedAtCreation', [false, true])
+ .combineWithParams([
+ { size: 12, range1: [], range2: [8] },
+ { size: 12, range1: [], range2: [0, 8] },
+ { size: 12, range1: [0, 8], range2: [8] },
+ { size: 12, range1: [8], range2: [0, 8] },
+ { size: 28, range1: [], range2: [8, 8] },
+ { size: 28, range1: [8, 16], range2: [16, 8] },
+ { size: 32, range1: [16, 12], range2: [8, 16] },
+ { size: 32, range1: [8, 8], range2: [24, 4] },
+ ])
+ )
+ .fn(async t => {
+ const { size, range1, range2, mappedAtCreation } = t.params;
+ const [rangeOffset1, rangeSize1] = reifyMapRange(size, range1);
+ const [rangeOffset2, rangeSize2] = reifyMapRange(size, range2);
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation,
+ size,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
+
+ // If the buffer is not mappedAtCreation map it now.
+ if (!mappedAtCreation) {
+ await buffer.mapAsync(GPUMapMode.WRITE);
+ }
+
+ // Set the initial contents of the buffer.
+ const init = buffer.getMappedRange(...range1);
+
+ assert(init.byteLength === rangeSize1);
+ const expectedBuffer = new ArrayBuffer(size);
+ const expected = new Uint32Array(
+ expectedBuffer,
+ rangeOffset1,
+ rangeSize1 / Uint32Array.BYTES_PER_ELEMENT
+ );
+
+ const data = new Uint32Array(init);
+ for (let i = 0; i < data.length; ++i) {
+ data[i] = expected[i] = i + 1;
+ }
+ buffer.unmap();
+
+ // Write to a second range of the buffer
+ await buffer.mapAsync(GPUMapMode.WRITE, ...range2);
+ const init2 = buffer.getMappedRange(...range2);
+
+ assert(init2.byteLength === rangeSize2);
+ const expected2 = new Uint32Array(
+ expectedBuffer,
+ rangeOffset2,
+ rangeSize2 / Uint32Array.BYTES_PER_ELEMENT
+ );
+
+ const data2 = new Uint32Array(init2);
+ for (let i = 0; i < data2.length; ++i) {
+ data2[i] = expected2[i] = 0;
+ }
+ buffer.unmap();
+
+ // Verify that the range of the buffer which was not overwritten was preserved.
+ t.expectGPUBufferValuesEqual(buffer, expected, rangeOffset1);
+ });
+
+g.test('mapAsync,read')
+ .desc(
+ `Use mappedAtCreation to initialize various ranges of variously-sized buffers, then
+map-read and check the read-back result.`
+ )
+ .params(u =>
+ u
+ .combine('mapAsyncRegionLeft', mapRegionBoundModes)
+ .combine('mapAsyncRegionRight', mapRegionBoundModes)
+ .beginSubcases()
+ .combineWithParams(kSubcases)
+ )
+ .fn(async t => {
+ const { size, range } = t.params;
+ const [rangeOffset, rangeSize] = reifyMapRange(size, range);
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+ const init = buffer.getMappedRange(...range);
+
+ assert(init.byteLength === rangeSize);
+ const expected = new Uint32Array(new ArrayBuffer(rangeSize));
+ const data = new Uint32Array(init);
+ for (let i = 0; i < data.length; ++i) {
+ data[i] = expected[i] = i + 1;
+ }
+ buffer.unmap();
+
+ const mapRegion = getRegionForMap(size, [rangeOffset, rangeSize], t.params);
+ await buffer.mapAsync(GPUMapMode.READ, ...mapRegion);
+ const actual = new Uint8Array(buffer.getMappedRange(...range));
+ t.expectOK(checkElementsEqual(actual, new Uint8Array(expected.buffer)));
+ });
+
+g.test('mapAsync,read,typedArrayAccess')
+ .desc(`Use various TypedArray types to read back from a mapped buffer`)
+ .params(u =>
+ u
+ .combine('mapAsyncRegionLeft', mapRegionBoundModes)
+ .combine('mapAsyncRegionRight', mapRegionBoundModes)
+ .beginSubcases()
+ .combineWithParams([
+ { size: 80, range: [] },
+ { size: 160, range: [] },
+ { size: 160, range: [0, 80] },
+ { size: 160, range: [80] },
+ { size: 160, range: [40, 120] },
+ { size: 160, range: [40] },
+ ])
+ )
+ .fn(async t => {
+ const { size, range } = t.params;
+ const [rangeOffset, rangeSize] = reifyMapRange(size, range);
+
+ // Fill an array buffer with a variety of values of different types.
+ const expectedArrayBuffer = new ArrayBuffer(80);
+ const uint8Expected = new Uint8Array(expectedArrayBuffer, 0, 2);
+ uint8Expected[0] = 1;
+ uint8Expected[1] = 255;
+
+ const int8Expected = new Int8Array(expectedArrayBuffer, 2, 2);
+ int8Expected[0] = -1;
+ int8Expected[1] = 127;
+
+ const uint16Expected = new Uint16Array(expectedArrayBuffer, 4, 2);
+ uint16Expected[0] = 1;
+ uint16Expected[1] = 65535;
+
+ const int16Expected = new Int16Array(expectedArrayBuffer, 8, 2);
+ int16Expected[0] = -1;
+ int16Expected[1] = 32767;
+
+ const uint32Expected = new Uint32Array(expectedArrayBuffer, 12, 2);
+ uint32Expected[0] = 1;
+ uint32Expected[1] = 4294967295;
+
+ const int32Expected = new Int32Array(expectedArrayBuffer, 20, 2);
+ int32Expected[2] = -1;
+ int32Expected[3] = 2147483647;
+
+ const float32Expected = new Float32Array(expectedArrayBuffer, 28, 3);
+ float32Expected[0] = 1;
+ float32Expected[1] = -1;
+ float32Expected[2] = 12345.6789;
+
+ const float64Expected = new Float64Array(expectedArrayBuffer, 40, 5);
+ float64Expected[0] = 1;
+ float64Expected[1] = -1;
+ float64Expected[2] = 12345.6789;
+ float64Expected[3] = Number.MAX_VALUE;
+ float64Expected[4] = Number.MIN_VALUE;
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+ const init = buffer.getMappedRange(...range);
+
+ // Copy the expected values into the mapped range.
+ assert(init.byteLength === rangeSize);
+ memcpy({ src: expectedArrayBuffer }, { dst: init });
+ buffer.unmap();
+
+ const mapRegion = getRegionForMap(size, [rangeOffset, rangeSize], t.params);
+ await buffer.mapAsync(GPUMapMode.READ, ...mapRegion);
+ const mappedArrayBuffer = buffer.getMappedRange(...range);
+ t.expectOK(checkElementsEqual(new Uint8Array(mappedArrayBuffer, 0, 2), uint8Expected));
+ t.expectOK(checkElementsEqual(new Int8Array(mappedArrayBuffer, 2, 2), int8Expected));
+ t.expectOK(checkElementsEqual(new Uint16Array(mappedArrayBuffer, 4, 2), uint16Expected));
+ t.expectOK(checkElementsEqual(new Int16Array(mappedArrayBuffer, 8, 2), int16Expected));
+ t.expectOK(checkElementsEqual(new Uint32Array(mappedArrayBuffer, 12, 2), uint32Expected));
+ t.expectOK(checkElementsEqual(new Int32Array(mappedArrayBuffer, 20, 2), int32Expected));
+ t.expectOK(checkElementsEqual(new Float32Array(mappedArrayBuffer, 28, 3), float32Expected));
+ t.expectOK(checkElementsEqual(new Float64Array(mappedArrayBuffer, 40, 5), float64Expected));
+ });
+
+g.test('mappedAtCreation')
+ .desc(
+ `Use mappedAtCreation to write to various ranges of variously-sized buffers created either
+with or without the MAP_WRITE usage (since this could affect the mappedAtCreation upload path),
+then expectContents (which does copyBufferToBuffer + map-read) to ensure the contents were written.`
+ )
+ .params(u =>
+ u //
+ .combine('mappable', [false, true])
+ .beginSubcases()
+ .combineWithParams(kSubcases)
+ )
+ .fn(async t => {
+ const { size, range, mappable } = t.params;
+ const [, rangeSize] = reifyMapRange(size, range);
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size,
+ usage: GPUBufferUsage.COPY_SRC | (mappable ? GPUBufferUsage.MAP_WRITE : 0),
+ });
+ const arrayBuffer = buffer.getMappedRange(...range);
+ t.checkMapWrite(buffer, range[0] ?? 0, arrayBuffer, rangeSize);
+ });
+
+g.test('remapped_for_write')
+ .desc(
+ `Use mappedAtCreation or mapAsync to write to various ranges of variously-sized buffers created
+with the MAP_WRITE usage, then mapAsync again and ensure that the previously written values are
+still present in the mapped buffer.`
+ )
+ .params(u =>
+ u //
+ .combine('mapAsyncRegionLeft', mapRegionBoundModes)
+ .combine('mapAsyncRegionRight', mapRegionBoundModes)
+ .beginSubcases()
+ .combine('mappedAtCreation', [false, true])
+ .combineWithParams(kSubcases)
+ )
+ .fn(async t => {
+ const { size, range, mappedAtCreation } = t.params;
+ const [rangeOffset, rangeSize] = reifyMapRange(size, range);
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation,
+ size,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
+
+ // If the buffer is not mappedAtCreation map it now.
+ if (!mappedAtCreation) {
+ await buffer.mapAsync(GPUMapMode.WRITE);
+ }
+
+ // Set the initial contents of the buffer.
+ const init = buffer.getMappedRange(...range);
+
+ assert(init.byteLength === rangeSize);
+ const expected = new Uint32Array(new ArrayBuffer(rangeSize));
+ const data = new Uint32Array(init);
+ for (let i = 0; i < data.length; ++i) {
+ data[i] = expected[i] = i + 1;
+ }
+ buffer.unmap();
+
+ // Check that upon remapping the for WRITE the values in the buffer are
+ // still the same.
+ const mapRegion = getRegionForMap(size, [rangeOffset, rangeSize], t.params);
+ await buffer.mapAsync(GPUMapMode.WRITE, ...mapRegion);
+ const actual = new Uint8Array(buffer.getMappedRange(...range));
+ t.expectOK(checkElementsEqual(actual, new Uint8Array(expected.buffer)));
+ });
+
+g.test('mappedAtCreation,mapState')
+ .desc('Test that exposed map state of buffer created with mappedAtCreation has expected values.')
+ .params(u =>
+ u
+ .combine('validationError', [false, true])
+ .combine('afterUnmap', [false, true])
+ .combine('afterDestroy', [false, true])
+ )
+ .fn(async t => {
+ const { validationError, afterUnmap, afterDestroy } = t.params;
+ const size = 8;
+ const range = [0, 8];
+
+ let buffer;
+ t.expectValidationError(() => {
+ buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size,
+ usage: validationError ? 0 : GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
+ }, validationError);
+
+ // mapState must be "mapped" regardless of validation error
+ t.expect(buffer.mapState === 'mapped');
+
+ // getMappedRange must not change the map state
+ buffer.getMappedRange(...range);
+ t.expect(buffer.mapState === 'mapped');
+
+ if (afterUnmap) {
+ buffer.unmap();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+
+ if (afterDestroy) {
+ buffer.destroy();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+ });
+
+g.test('mapAsync,mapState')
+ .desc('Test that exposed map state of buffer mapped with mapAsync has expected values.')
+ .params(u =>
+ u
+ .combine('bufferCreationValidationError', [false, true])
+ .combine('mapAsyncValidationError', [false, true])
+ .combine('beforeUnmap', [false, true])
+ .combine('beforeDestroy', [false, true])
+ .combine('afterUnmap', [false, true])
+ .combine('afterDestroy', [false, true])
+ )
+ .fn(async t => {
+ const {
+ bufferCreationValidationError,
+ mapAsyncValidationError,
+ beforeUnmap,
+ beforeDestroy,
+ afterUnmap,
+ afterDestroy,
+ } = t.params;
+ const size = 8;
+ const range = [0, 8];
+
+ let buffer;
+ t.expectValidationError(() => {
+ buffer = t.device.createBuffer({
+ mappedAtCreation: false,
+ size,
+ usage: bufferCreationValidationError
+ ? 0
+ : GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
+ }, bufferCreationValidationError);
+
+ t.expect(buffer.mapState === 'unmapped');
+
+ {
+ let promise;
+ t.expectValidationError(() => {
+ promise = buffer.mapAsync(mapAsyncValidationError ? 0 : GPUMapMode.WRITE);
+ }, bufferCreationValidationError || mapAsyncValidationError);
+ t.expect(buffer.mapState === 'pending');
+
+ try {
+ if (beforeUnmap) {
+ buffer.unmap();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+ if (beforeDestroy) {
+ buffer.destroy();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+
+ await promise;
+ t.expect(buffer.mapState === 'mapped');
+
+ // getMappedRange must not change the map state
+ buffer.getMappedRange(...range);
+ t.expect(buffer.mapState === 'mapped');
+ } catch {
+ // unmapped before resolve, destroyed before resolve, or mapAsync validation error
+ // will end up with rejection and 'unmapped'
+ t.expect(buffer.mapState === 'unmapped');
+ }
+ }
+
+ // If buffer is already mapped test mapAsync on already mapped buffer
+ if (buffer.mapState === 'mapped') {
+ // mapAsync on already mapped buffer must be rejected with a validation error
+ // and the map state must keep 'mapped'
+ let promise;
+ t.expectValidationError(() => {
+ promise = buffer.mapAsync(GPUMapMode.WRITE);
+ }, true);
+ t.expect(buffer.mapState === 'mapped');
+
+ try {
+ await promise;
+ t.fail('mapAsync on already mapped buffer must not succeed.');
+ } catch {
+ t.expect(buffer.mapState === 'mapped');
+ }
+ }
+
+ if (afterUnmap) {
+ buffer.unmap();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+
+ if (afterDestroy) {
+ buffer.destroy();
+ t.expect(buffer.mapState === 'unmapped');
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_ArrayBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_ArrayBuffer.spec.js
new file mode 100644
index 0000000000..d006e40486
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_ArrayBuffer.spec.js
@@ -0,0 +1,90 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for the behavior of ArrayBuffers returned by getMappedRange.
+
+TODO: Add tests that transfer to another thread instead of just using MessageChannel.
+TODO: Add tests for any other Web APIs that can detach ArrayBuffers.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { timeout } from '../../../../common/util/timeout.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsEqual } from '../../../util/check_contents.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('postMessage')
+ .desc(
+ `Using postMessage to send a getMappedRange-returned ArrayBuffer throws a TypeError
+ if it was included in the transfer list. Otherwise, it makes a copy.
+ Test combinations of transfer={false, true}, mapMode={read,write}.`
+ )
+ .params(u =>
+ u //
+ .combine('transfer', [false, true])
+ .combine('mapMode', ['READ', 'WRITE'])
+ )
+ .fn(async t => {
+ const { transfer, mapMode } = t.params;
+ const kSize = 1024;
+
+ // Populate initial data.
+ const initialData = new Uint32Array(new ArrayBuffer(kSize));
+ for (let i = 0; i < initialData.length; ++i) {
+ initialData[i] = i;
+ }
+
+ const buf = t.makeBufferWithContents(
+ initialData,
+ mapMode === 'WRITE' ? GPUBufferUsage.MAP_WRITE : GPUBufferUsage.MAP_READ
+ );
+
+ await buf.mapAsync(GPUMapMode[mapMode]);
+ const ab1 = buf.getMappedRange();
+ t.expect(ab1.byteLength === kSize, 'ab1 should have the size of the buffer');
+
+ const mc = new MessageChannel();
+ const ab2Promise = new Promise(resolve => {
+ mc.port2.onmessage = ev => {
+ if (transfer) {
+ t.fail(
+ `postMessage with ab1 in transfer list should not be received. Unexpected message: ${ev.data}`
+ );
+ } else {
+ resolve(ev.data);
+ }
+ };
+ });
+
+ if (transfer) {
+ t.shouldThrow('TypeError', () => mc.port1.postMessage(ab1, [ab1]));
+ // Wait to make sure the postMessage isn't received.
+ await new Promise(resolve => timeout(resolve, 100));
+ } else {
+ mc.port1.postMessage(ab1);
+ }
+ t.expect(ab1.byteLength === kSize, 'after postMessage, ab1 should not be detached');
+
+ if (!transfer) {
+ const ab2 = await ab2Promise;
+ t.expect(ab2.byteLength === kSize, 'ab2 should be the same size');
+ const ab2Data = new Uint32Array(ab2, 0, initialData.length);
+ // ab2 should have the same initial contents.
+ t.expectOK(checkElementsEqual(ab2Data, initialData));
+
+ // Mutations to ab2 should not be visible in ab1.
+ const ab1Data = new Uint32Array(ab1, 0, initialData.length);
+ const abs2NewData = initialData.slice().reverse();
+ for (let i = 0; i < ab2Data.length; ++i) {
+ ab2Data[i] = abs2NewData[i];
+ }
+ t.expectOK(checkElementsEqual(ab1Data, initialData));
+ t.expectOK(checkElementsEqual(ab2Data, abs2NewData));
+ }
+
+ buf.unmap();
+ t.expect(ab1.byteLength === 0, 'after unmap, ab1 should be detached');
+
+ // Transferring an already-detached ArrayBuffer is a DataCloneError.
+ t.shouldThrow('DataCloneError', () => mc.port1.postMessage(ab1, [ab1]));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js
new file mode 100644
index 0000000000..c1cf0715df
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js
@@ -0,0 +1,80 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+ Tests that TypedArrays created when mapping a GPUBuffer are detached when the
+ buffer is unmapped or destroyed.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { getGPU } from '../../../../common/util/navigator_gpu.js';
+import { assert } from '../../../../common/util/util.js';
+import { GPUConst } from '../../../constants.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('while_mapped')
+ .desc(
+ `
+ Test that a mapped buffers are able to properly detach.
+ - Tests {mappable, unmappable mapAtCreation, mappable mapAtCreation}
+ - Tests while {mapped, mapped at creation, mapped at creation then unmapped and mapped again}
+ - When {unmap, destroy, unmap && destroy, device.destroy} is called`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('mappedAtCreation', [false, true])
+ .combineWithParams([
+ { usage: GPUConst.BufferUsage.COPY_SRC },
+ { usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC },
+ { usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ },
+ {
+ usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC,
+ mapMode: GPUConst.MapMode.WRITE,
+ },
+ {
+ usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ,
+ mapMode: GPUConst.MapMode.READ,
+ },
+ ])
+ .combineWithParams([
+ { unmap: true, destroy: false },
+ { unmap: false, destroy: true },
+ { unmap: true, destroy: true },
+ { unmap: false, destroy: false, deviceDestroy: true },
+ ])
+ .unless(p => p.mappedAtCreation === false && p.mapMode === undefined)
+ )
+ .fn(async t => {
+ const { usage, mapMode, mappedAtCreation, unmap, destroy, deviceDestroy } = t.params;
+
+ let device = t.device;
+ if (deviceDestroy) {
+ const adapter = await getGPU().requestAdapter();
+ assert(adapter !== null);
+ device = await adapter.requestDevice();
+ }
+ const buffer = device.createBuffer({
+ size: 4,
+ usage,
+ mappedAtCreation,
+ });
+
+ if (mapMode !== undefined) {
+ if (mappedAtCreation) {
+ buffer.unmap();
+ }
+ await buffer.mapAsync(mapMode);
+ }
+
+ const arrayBuffer = buffer.getMappedRange();
+ const view = new Uint8Array(arrayBuffer);
+ t.expect(arrayBuffer.byteLength === 4);
+ t.expect(view.length === 4);
+
+ if (unmap) buffer.unmap();
+ if (destroy) buffer.destroy();
+ if (deviceDestroy) device.destroy();
+
+ t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached');
+ t.expect(view.byteLength === 0, 'ArrayBufferView should be detached');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js
new file mode 100644
index 0000000000..85e5c432c2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js
@@ -0,0 +1,121 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description =
+ 'Test out-of-memory conditions creating large mappable/mappedAtCreation buffers.';
+import { kUnitCaseParamsBuilder } from '../../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kBufferUsages } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { kMaxSafeMultipleOf8 } from '../../../util/math.js';
+
+const oomAndSizeParams = kUnitCaseParamsBuilder
+ .combine('oom', [false, true])
+ .expand('size', ({ oom }) => {
+ return oom
+ ? [
+ kMaxSafeMultipleOf8,
+ 0x20_0000_0000, // 128 GB
+ ]
+ : [16];
+ });
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('mapAsync')
+ .desc(
+ `Test creating a large mappable buffer should produce an out-of-memory error if allocation fails.
+ - The resulting buffer is an error buffer, so mapAsync rejects and produces a validation error.
+ - Calling getMappedRange should throw an OperationError because the buffer is not in the mapped state.
+ - unmap() doesn't throw an error even if mapping failed, and otherwise should detach the ArrayBuffer.
+`
+ )
+ .params(
+ oomAndSizeParams //
+ .beginSubcases()
+ .combine('write', [false, true])
+ .combine('unmapBeforeResolve', [false, true])
+ )
+ .fn(async t => {
+ const { oom, write, size, unmapBeforeResolve } = t.params;
+
+ const buffer = t.expectGPUError(
+ 'out-of-memory',
+ () =>
+ t.device.createBuffer({
+ size,
+ usage: write ? GPUBufferUsage.MAP_WRITE : GPUBufferUsage.MAP_READ,
+ }),
+ oom
+ );
+
+ let promise;
+ // Should be a validation error since the buffer is invalid.
+ // Unmap abort error shouldn't cause a validation error.
+ t.expectValidationError(() => {
+ promise = buffer.mapAsync(write ? GPUMapMode.WRITE : GPUMapMode.READ);
+ }, oom);
+
+ if (oom) {
+ if (unmapBeforeResolve) {
+ // Should reject with abort error because buffer will be unmapped
+ // before validation check finishes.
+ t.shouldReject('AbortError', promise);
+ } else {
+ // Should also reject in addition to the validation error.
+ t.shouldReject('OperationError', promise);
+
+ // Wait for validation error before unmap to ensure validation check
+ // ends before unmap.
+ try {
+ await promise;
+ throw new Error('The promise should be rejected.');
+ } catch {
+ // Should cause an exception because the promise should be rejected.
+ }
+ }
+
+ // Should throw an OperationError because the buffer is not mapped.
+ // Note: not a RangeError because the state of the buffer is checked first.
+ t.shouldThrow('OperationError', () => {
+ buffer.getMappedRange();
+ });
+
+ // Should't be a validation error even if the buffer failed to be mapped.
+ buffer.unmap();
+ } else {
+ await promise;
+ const arraybuffer = buffer.getMappedRange();
+ t.expect(arraybuffer.byteLength === size);
+ buffer.unmap();
+ t.expect(arraybuffer.byteLength === 0, 'Mapping should be detached');
+ }
+ });
+
+g.test('mappedAtCreation')
+ .desc(
+ `Test creating a very large buffer mappedAtCreation buffer should throw a RangeError only
+ because such a large allocation cannot be created when we initialize an active buffer mapping.
+`
+ )
+ .params(
+ oomAndSizeParams //
+ .beginSubcases()
+ .combine('usage', kBufferUsages)
+ )
+ .fn(async t => {
+ const { oom, usage, size } = t.params;
+
+ const f = () => t.device.createBuffer({ mappedAtCreation: true, size, usage });
+
+ if (oom) {
+ // getMappedRange is normally valid on OOM buffers, but this one fails because the
+ // (default) range is too large to create the returned ArrayBuffer.
+ t.shouldThrow('RangeError', f);
+ } else {
+ const buffer = f();
+ const mapping = buffer.getMappedRange();
+ t.expect(mapping.byteLength === size, 'Mapping should be successful');
+ buffer.unmap();
+ t.expect(mapping.byteLength === 0, 'Mapping should be detached');
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/mapping_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/mapping_test.js
new file mode 100644
index 0000000000..7a69968a9f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/mapping_test.js
@@ -0,0 +1,35 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+export class MappingTest extends GPUTest {
+ checkMapWrite(buffer, offset, mappedContents, size) {
+ this.checkMapWriteZeroed(mappedContents, size);
+
+ const mappedView = new Uint32Array(mappedContents);
+ const expected = new Uint32Array(new ArrayBuffer(size));
+ assert(mappedView.byteLength === size);
+ for (let i = 0; i < mappedView.length; ++i) {
+ mappedView[i] = expected[i] = i + 1;
+ }
+ buffer.unmap();
+
+ this.expectGPUBufferValuesEqual(buffer, expected, offset);
+ }
+
+ checkMapWriteZeroed(arrayBuffer, expectedSize) {
+ this.expect(arrayBuffer.byteLength === expectedSize);
+ const view = new Uint8Array(arrayBuffer);
+ this.expectZero(view);
+ }
+
+ expectZero(actual) {
+ const size = actual.byteLength;
+ for (let i = 0; i < size; ++i) {
+ if (actual[i] !== 0) {
+ this.fail(`at [${i}], expected zero, got ${actual[i]}`);
+ break;
+ }
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/threading.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/threading.spec.js
new file mode 100644
index 0000000000..d30e5813b3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/buffers/threading.spec.js
@@ -0,0 +1,30 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for valid operations with various client-side thread-shared state of GPUBuffers.
+
+States to test:
+- mapping pending
+- mapped
+- mapped at creation
+- mapped at creation, then unmapped
+- mapped at creation, then unmapped, then re-mapped
+- destroyed
+
+TODO: Look for more things to test.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('serialize')
+ .desc(
+ `Copy a GPUBuffer to another thread while it is in various states on
+{the sending thread, yet another thread}.`
+ )
+ .unimplemented();
+
+g.test('destroyed')
+ .desc(`Destroy on one thread while in various states in another thread.`)
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js
new file mode 100644
index 0000000000..b75b1800e8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js
@@ -0,0 +1,104 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Basic tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { memcpy } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('empty').fn(async t => {
+ const encoder = t.device.createCommandEncoder();
+ const cmd = encoder.finish();
+ t.device.queue.submit([cmd]);
+});
+
+g.test('b2t2b').fn(async t => {
+ const data = new Uint32Array([0x01020304]);
+
+ const src = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ memcpy({ src: data }, { dst: src.getMappedRange() });
+ src.unmap();
+
+ const dst = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const mid = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'rgba8uint',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToTexture(
+ { buffer: src, bytesPerRow: 256 },
+ { texture: mid, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ encoder.copyTextureToBuffer(
+ { texture: mid, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dst, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(dst, data);
+});
+
+g.test('b2t2t2b').fn(async t => {
+ const data = new Uint32Array([0x01020304]);
+
+ const src = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ memcpy({ src: data }, { dst: src.getMappedRange() });
+ src.unmap();
+
+ const dst = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const midDesc = {
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'rgba8uint',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ };
+ const mid1 = t.device.createTexture(midDesc);
+ const mid2 = t.device.createTexture(midDesc);
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToTexture(
+ { buffer: src, bytesPerRow: 256 },
+ { texture: mid1, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ encoder.copyTextureToTexture(
+ { texture: mid1, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { texture: mid2, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ encoder.copyTextureToBuffer(
+ { texture: mid2, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dst, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(dst, data);
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/clearBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/clearBuffer.spec.js
new file mode 100644
index 0000000000..bbdd854536
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/clearBuffer.spec.js
@@ -0,0 +1,55 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API operations tests for clearBuffer.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('clear')
+ .desc(
+ `Validate the correctness of the clear by filling the srcBuffer with testable data, doing
+ clearBuffer(), and verifying the content of the whole srcBuffer with MapRead:
+ Clear {4 bytes, part of, the whole} buffer {with, without} a non-zero valid offset that
+ - covers the whole buffer
+ - covers the beginning of the buffer
+ - covers the end of the buffer
+ - covers neither the beginning nor the end of the buffer`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('offset', [0, 4, 8, 16, undefined])
+ .combine('size', [0, 4, 8, 16, undefined])
+ .expand('bufferSize', p => [
+ (p.offset ?? 0) + (p.size ?? 16),
+ (p.offset ?? 0) + (p.size ?? 16) + 8,
+ ])
+ )
+ .fn(async t => {
+ const { offset, size, bufferSize } = t.params;
+
+ const bufferData = new Uint8Array(bufferSize);
+ for (let i = 0; i < bufferSize; ++i) {
+ bufferData[i] = i + 1;
+ }
+
+ const buffer = t.makeBufferWithContents(
+ bufferData,
+ GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
+ );
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.clearBuffer(buffer, offset, size);
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectOffset = offset ?? 0;
+ const expectSize = size ?? bufferSize - expectOffset;
+
+ for (let i = 0; i < expectSize; ++i) {
+ bufferData[expectOffset + i] = 0;
+ }
+
+ t.expectGPUBufferValuesEqual(buffer, bufferData);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyBufferToBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyBufferToBuffer.spec.js
new file mode 100644
index 0000000000..220f093e46
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyBufferToBuffer.spec.js
@@ -0,0 +1,110 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = 'copyBufferToBuffer operation tests';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('single')
+ .desc(
+ `Validate the correctness of the copy by filling the srcBuffer with testable data, doing
+ CopyBufferToBuffer() copy, and verifying the content of the whole dstBuffer with MapRead:
+ Copy {4 bytes, part of, the whole} srcBuffer to the dstBuffer {with, without} a non-zero valid
+ srcOffset that
+ - covers the whole dstBuffer
+ - covers the beginning of the dstBuffer
+ - covers the end of the dstBuffer
+ - covers neither the beginning nor the end of the dstBuffer`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcOffset', [0, 4, 8, 16])
+ .combine('dstOffset', [0, 4, 8, 16])
+ .combine('copySize', [0, 4, 8, 16])
+ .expand('srcBufferSize', p => [p.srcOffset + p.copySize, p.srcOffset + p.copySize + 8])
+ .expand('dstBufferSize', p => [p.dstOffset + p.copySize, p.dstOffset + p.copySize + 8])
+ )
+ .fn(async t => {
+ const { srcOffset, dstOffset, copySize, srcBufferSize, dstBufferSize } = t.params;
+
+ const srcData = new Uint8Array(srcBufferSize);
+ for (let i = 0; i < srcBufferSize; ++i) {
+ srcData[i] = i + 1;
+ }
+
+ const src = t.makeBufferWithContents(srcData, GPUBufferUsage.COPY_SRC);
+
+ const dst = t.device.createBuffer({
+ size: dstBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(dst);
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToBuffer(src, srcOffset, dst, dstOffset, copySize);
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectedDstData = new Uint8Array(dstBufferSize);
+ for (let i = 0; i < copySize; ++i) {
+ expectedDstData[dstOffset + i] = srcData[srcOffset + i];
+ }
+
+ t.expectGPUBufferValuesEqual(dst, expectedDstData);
+ });
+
+g.test('state_transitions')
+ .desc(
+ `Test proper state transitions/barriers happen between copy commands.
+ Copy part of src to dst, then a different part of dst to src, and check contents of both.`
+ )
+ .fn(async t => {
+ const srcData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
+ const dstData = new Uint8Array([10, 20, 30, 40, 50, 60, 70, 80]);
+
+ const src = t.makeBufferWithContents(
+ srcData,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ const dst = t.makeBufferWithContents(
+ dstData,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToBuffer(src, 0, dst, 4, 4);
+ encoder.copyBufferToBuffer(dst, 0, src, 4, 4);
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectedSrcData = new Uint8Array([1, 2, 3, 4, 10, 20, 30, 40]);
+ const expectedDstData = new Uint8Array([10, 20, 30, 40, 1, 2, 3, 4]);
+ t.expectGPUBufferValuesEqual(src, expectedSrcData);
+ t.expectGPUBufferValuesEqual(dst, expectedDstData);
+ });
+
+g.test('copy_order')
+ .desc(
+ `Test copy commands in one command buffer occur in the correct order.
+ First copies one region from src to dst, then another region from src to an overlapping region
+ of dst, then checks the dst buffer's contents.`
+ )
+ .fn(async t => {
+ const srcData = new Uint32Array([1, 2, 3, 4, 5, 6, 7, 8]);
+
+ const src = t.makeBufferWithContents(srcData, GPUBufferUsage.COPY_SRC);
+
+ const dst = t.device.createBuffer({
+ size: srcData.length * 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(dst);
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToBuffer(src, 0, dst, 0, 16);
+ encoder.copyBufferToBuffer(src, 16, dst, 8, 16);
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectedDstData = new Uint32Array([1, 2, 5, 6, 7, 8, 0, 0]);
+ t.expectGPUBufferValuesEqual(dst, expectedDstData);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js
new file mode 100644
index 0000000000..1cbab855e6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.js
@@ -0,0 +1,1588 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `copyTextureToTexture operation tests`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, memcpy, unreachable } from '../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kRegularTextureFormats,
+ kCompressedTextureFormats,
+ depthStencilFormatAspectSize,
+ kBufferSizeAlignment,
+ kDepthStencilFormats,
+ kMinDynamicBufferOffsetAlignment,
+ kTextureDimensions,
+ textureDimensionAndFormatCompatible,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { makeBufferWithContents } from '../../../util/buffer.js';
+import { checkElementsEqual, checkElementsEqualEither } from '../../../util/check_contents.js';
+import { align } from '../../../util/math.js';
+import { physicalMipSize } from '../../../util/texture/base.js';
+import { DataArrayGenerator } from '../../../util/texture/data_generation.js';
+import { kBytesPerRowAlignment, dataBytesForCopyOrFail } from '../../../util/texture/layout.js';
+
+const dataGenerator = new DataArrayGenerator();
+
+class F extends GPUTest {
+ GetInitialDataPerMipLevel(dimension, textureSize, format, mipLevel) {
+ const textureSizeAtLevel = physicalMipSize(textureSize, format, dimension, mipLevel);
+ const bytesPerBlock = kTextureFormatInfo[format].bytesPerBlock;
+ const blockWidthInTexel = kTextureFormatInfo[format].blockWidth;
+ const blockHeightInTexel = kTextureFormatInfo[format].blockHeight;
+ const blocksPerSubresource =
+ (textureSizeAtLevel.width / blockWidthInTexel) *
+ (textureSizeAtLevel.height / blockHeightInTexel);
+
+ const byteSize = bytesPerBlock * blocksPerSubresource * textureSizeAtLevel.depthOrArrayLayers;
+ return dataGenerator.generateView(byteSize);
+ }
+
+ GetInitialStencilDataPerMipLevel(textureSize, format, mipLevel) {
+ const textureSizeAtLevel = physicalMipSize(textureSize, format, '2d', mipLevel);
+ const aspectBytesPerBlock = depthStencilFormatAspectSize(format, 'stencil-only');
+ const byteSize =
+ aspectBytesPerBlock *
+ textureSizeAtLevel.width *
+ textureSizeAtLevel.height *
+ textureSizeAtLevel.depthOrArrayLayers;
+ return dataGenerator.generateView(byteSize);
+ }
+
+ DoCopyTextureToTextureTest(
+ dimension,
+ srcTextureSize,
+ dstTextureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+
+ srcCopyLevel,
+ dstCopyLevel
+ ) {
+ const mipLevelCount = dimension === '1d' ? 1 : 4;
+
+ // Create srcTexture and dstTexture
+ const srcTextureDesc = {
+ dimension,
+ size: srcTextureSize,
+ format: srcFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ mipLevelCount,
+ };
+ const srcTexture = this.device.createTexture(srcTextureDesc);
+ this.trackForCleanup(srcTexture);
+ const dstTextureDesc = {
+ dimension,
+ size: dstTextureSize,
+ format: dstFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ mipLevelCount,
+ };
+ const dstTexture = this.device.createTexture(dstTextureDesc);
+ this.trackForCleanup(dstTexture);
+
+ // Fill the whole subresource of srcTexture at srcCopyLevel with initialSrcData.
+ const initialSrcData = this.GetInitialDataPerMipLevel(
+ dimension,
+ srcTextureSize,
+ srcFormat,
+ srcCopyLevel
+ );
+
+ const srcTextureSizeAtLevel = physicalMipSize(
+ srcTextureSize,
+ srcFormat,
+ dimension,
+ srcCopyLevel
+ );
+
+ const bytesPerBlock = kTextureFormatInfo[srcFormat].bytesPerBlock;
+ const blockWidth = kTextureFormatInfo[srcFormat].blockWidth;
+ const blockHeight = kTextureFormatInfo[srcFormat].blockHeight;
+ const srcBlocksPerRow = srcTextureSizeAtLevel.width / blockWidth;
+ const srcBlockRowsPerImage = srcTextureSizeAtLevel.height / blockHeight;
+ this.device.queue.writeTexture(
+ { texture: srcTexture, mipLevel: srcCopyLevel },
+ initialSrcData,
+ {
+ bytesPerRow: srcBlocksPerRow * bytesPerBlock,
+ rowsPerImage: srcBlockRowsPerImage,
+ },
+ srcTextureSizeAtLevel
+ );
+
+ // Copy the region specified by copyBoxOffsets from srcTexture to dstTexture.
+ const dstTextureSizeAtLevel = physicalMipSize(
+ dstTextureSize,
+ dstFormat,
+ dimension,
+ dstCopyLevel
+ );
+
+ const minWidth = Math.min(srcTextureSizeAtLevel.width, dstTextureSizeAtLevel.width);
+ const minHeight = Math.min(srcTextureSizeAtLevel.height, dstTextureSizeAtLevel.height);
+ const minDepth = Math.min(
+ srcTextureSizeAtLevel.depthOrArrayLayers,
+ dstTextureSizeAtLevel.depthOrArrayLayers
+ );
+
+ const appliedSrcOffset = {
+ x: Math.min(copyBoxOffsets.srcOffset.x * blockWidth, minWidth),
+ y: Math.min(copyBoxOffsets.srcOffset.y * blockHeight, minHeight),
+ z: Math.min(copyBoxOffsets.srcOffset.z, minDepth),
+ };
+ const appliedDstOffset = {
+ x: Math.min(copyBoxOffsets.dstOffset.x * blockWidth, minWidth),
+ y: Math.min(copyBoxOffsets.dstOffset.y * blockHeight, minHeight),
+ z: Math.min(copyBoxOffsets.dstOffset.z, minDepth),
+ };
+
+ const appliedCopyWidth = Math.max(
+ minWidth +
+ copyBoxOffsets.copyExtent.width * blockWidth -
+ Math.max(appliedSrcOffset.x, appliedDstOffset.x),
+ 0
+ );
+
+ const appliedCopyHeight = Math.max(
+ minHeight +
+ copyBoxOffsets.copyExtent.height * blockHeight -
+ Math.max(appliedSrcOffset.y, appliedDstOffset.y),
+ 0
+ );
+
+ assert(appliedCopyWidth % blockWidth === 0 && appliedCopyHeight % blockHeight === 0);
+
+ const appliedCopyDepth = Math.max(
+ 0,
+ minDepth +
+ copyBoxOffsets.copyExtent.depthOrArrayLayers -
+ Math.max(appliedSrcOffset.z, appliedDstOffset.z)
+ );
+
+ assert(appliedCopyDepth >= 0);
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToTexture(
+ { texture: srcTexture, mipLevel: srcCopyLevel, origin: appliedSrcOffset },
+ { texture: dstTexture, mipLevel: dstCopyLevel, origin: appliedDstOffset },
+ { width: appliedCopyWidth, height: appliedCopyHeight, depthOrArrayLayers: appliedCopyDepth }
+ );
+
+ // Copy the whole content of dstTexture at dstCopyLevel to dstBuffer.
+ const dstBlocksPerRow = dstTextureSizeAtLevel.width / blockWidth;
+ const dstBlockRowsPerImage = dstTextureSizeAtLevel.height / blockHeight;
+ const bytesPerDstAlignedBlockRow = align(dstBlocksPerRow * bytesPerBlock, 256);
+ const dstBufferSize =
+ (dstBlockRowsPerImage * dstTextureSizeAtLevel.depthOrArrayLayers - 1) *
+ bytesPerDstAlignedBlockRow +
+ align(dstBlocksPerRow * bytesPerBlock, 4);
+ const dstBufferDesc = {
+ size: dstBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ };
+ const dstBuffer = this.device.createBuffer(dstBufferDesc);
+ this.trackForCleanup(dstBuffer);
+
+ encoder.copyTextureToBuffer(
+ { texture: dstTexture, mipLevel: dstCopyLevel },
+ {
+ buffer: dstBuffer,
+ bytesPerRow: bytesPerDstAlignedBlockRow,
+ rowsPerImage: dstBlockRowsPerImage,
+ },
+ dstTextureSizeAtLevel
+ );
+
+ this.device.queue.submit([encoder.finish()]);
+
+ // Fill expectedUint8DataWithPadding with the expected data of dstTexture. The other values in
+ // expectedUint8DataWithPadding are kept 0 to check if the texels untouched by the copy are 0
+ // (their previous values).
+ const expectedUint8DataWithPadding = new Uint8Array(dstBufferSize);
+ const expectedUint8Data = new Uint8Array(initialSrcData);
+
+ const appliedCopyBlocksPerRow = appliedCopyWidth / blockWidth;
+ const appliedCopyBlockRowsPerImage = appliedCopyHeight / blockHeight;
+ const srcCopyOffsetInBlocks = {
+ x: appliedSrcOffset.x / blockWidth,
+ y: appliedSrcOffset.y / blockHeight,
+ z: appliedSrcOffset.z,
+ };
+ const dstCopyOffsetInBlocks = {
+ x: appliedDstOffset.x / blockWidth,
+ y: appliedDstOffset.y / blockHeight,
+ z: appliedDstOffset.z,
+ };
+
+ for (let z = 0; z < appliedCopyDepth; ++z) {
+ const srcOffsetZ = srcCopyOffsetInBlocks.z + z;
+ const dstOffsetZ = dstCopyOffsetInBlocks.z + z;
+ for (let y = 0; y < appliedCopyBlockRowsPerImage; ++y) {
+ const dstOffsetYInBlocks = dstCopyOffsetInBlocks.y + y;
+ const expectedDataWithPaddingOffset =
+ bytesPerDstAlignedBlockRow * (dstBlockRowsPerImage * dstOffsetZ + dstOffsetYInBlocks) +
+ dstCopyOffsetInBlocks.x * bytesPerBlock;
+
+ const srcOffsetYInBlocks = srcCopyOffsetInBlocks.y + y;
+ const expectedDataOffset =
+ bytesPerBlock *
+ srcBlocksPerRow *
+ (srcBlockRowsPerImage * srcOffsetZ + srcOffsetYInBlocks) +
+ srcCopyOffsetInBlocks.x * bytesPerBlock;
+
+ const bytesInRow = appliedCopyBlocksPerRow * bytesPerBlock;
+ memcpy(
+ { src: expectedUint8Data, start: expectedDataOffset, length: bytesInRow },
+ { dst: expectedUint8DataWithPadding, start: expectedDataWithPaddingOffset }
+ );
+ }
+ }
+
+ let alternateExpectedData = expectedUint8DataWithPadding;
+ // For 8-byte snorm formats, allow an alternative encoding of -1.
+ // MAINTENANCE_TODO: Use textureContentIsOKByT2B with TexelView.
+ if (srcFormat.includes('snorm')) {
+ switch (srcFormat) {
+ case 'r8snorm':
+ case 'rg8snorm':
+ case 'rgba8snorm':
+ alternateExpectedData = alternateExpectedData.slice();
+ for (let i = 0; i < alternateExpectedData.length; ++i) {
+ if (alternateExpectedData[i] === 128) {
+ alternateExpectedData[i] = 129;
+ } else if (alternateExpectedData[i] === 129) {
+ alternateExpectedData[i] = 128;
+ }
+ }
+ break;
+ case 'bc4-r-snorm':
+ case 'bc5-rg-snorm':
+ case 'eac-r11snorm':
+ case 'eac-rg11snorm':
+ break;
+ default:
+ unreachable();
+ }
+ }
+
+ // Verify the content of the whole subresource of dstTexture at dstCopyLevel (in dstBuffer) is expected.
+ this.expectGPUBufferValuesPassCheck(
+ dstBuffer,
+ alternateExpectedData === expectedUint8DataWithPadding
+ ? vals => checkElementsEqual(vals, expectedUint8DataWithPadding)
+ : vals =>
+ checkElementsEqualEither(vals, [expectedUint8DataWithPadding, alternateExpectedData]),
+ {
+ srcByteOffset: 0,
+ type: Uint8Array,
+ typedLength: expectedUint8DataWithPadding.length,
+ }
+ );
+ }
+
+ InitializeStencilAspect(
+ sourceTexture,
+ initialStencilData,
+ srcCopyLevel,
+ srcCopyBaseArrayLayer,
+ copySize
+ ) {
+ this.queue.writeTexture(
+ {
+ texture: sourceTexture,
+ mipLevel: srcCopyLevel,
+ aspect: 'stencil-only',
+ origin: { x: 0, y: 0, z: srcCopyBaseArrayLayer },
+ },
+ initialStencilData,
+ { bytesPerRow: copySize[0], rowsPerImage: copySize[1] },
+ copySize
+ );
+ }
+
+ VerifyStencilAspect(
+ destinationTexture,
+ initialStencilData,
+ dstCopyLevel,
+ dstCopyBaseArrayLayer,
+ copySize
+ ) {
+ const bytesPerRow = align(copySize[0], kBytesPerRowAlignment);
+ const rowsPerImage = copySize[1];
+ const outputBufferSize = align(
+ dataBytesForCopyOrFail({
+ layout: { bytesPerRow, rowsPerImage },
+ format: 'stencil8',
+ copySize,
+ method: 'CopyT2B',
+ }),
+ kBufferSizeAlignment
+ );
+
+ const outputBuffer = this.device.createBuffer({
+ size: outputBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(outputBuffer);
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToBuffer(
+ {
+ texture: destinationTexture,
+ aspect: 'stencil-only',
+ mipLevel: dstCopyLevel,
+ origin: { x: 0, y: 0, z: dstCopyBaseArrayLayer },
+ },
+ { buffer: outputBuffer, bytesPerRow, rowsPerImage },
+ copySize
+ );
+
+ this.queue.submit([encoder.finish()]);
+
+ const expectedStencilData = new Uint8Array(outputBufferSize);
+ for (let z = 0; z < copySize[2]; ++z) {
+ const initialOffsetPerLayer = z * copySize[0] * copySize[1];
+ const expectedOffsetPerLayer = z * bytesPerRow * rowsPerImage;
+ for (let y = 0; y < copySize[1]; ++y) {
+ const initialOffsetPerRow = initialOffsetPerLayer + y * copySize[0];
+ const expectedOffsetPerRow = expectedOffsetPerLayer + y * bytesPerRow;
+ memcpy(
+ { src: initialStencilData, start: initialOffsetPerRow, length: copySize[0] },
+ { dst: expectedStencilData, start: expectedOffsetPerRow }
+ );
+ }
+ }
+ this.expectGPUBufferValuesEqual(outputBuffer, expectedStencilData);
+ }
+
+ GetRenderPipelineForT2TCopyWithDepthTests(bindGroupLayout, hasColorAttachment, depthStencil) {
+ const renderPipelineDescriptor = {
+ layout: this.device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Params {
+ copyLayer: f32
+ };
+ @group(0) @binding(0) var<uniform> param: Params;
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)-> @builtin(position) vec4<f32> {
+ var depthValue = 0.5 + 0.2 * sin(param.copyLayer);
+ var pos : array<vec3<f32>, 6> = array<vec3<f32>, 6>(
+ vec3<f32>(-1.0, 1.0, depthValue),
+ vec3<f32>(-1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, 1.0, 1.0),
+ vec3<f32>(-1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, 1.0, 1.0),
+ vec3<f32>( 1.0, -1.0, depthValue));
+ return vec4<f32>(pos[VertexIndex], 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ depthStencil,
+ };
+ if (hasColorAttachment) {
+ renderPipelineDescriptor.fragment = {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ };
+ }
+ return this.device.createRenderPipeline(renderPipelineDescriptor);
+ }
+
+ GetBindGroupLayoutForT2TCopyWithDepthTests() {
+ return this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.VERTEX,
+ buffer: {
+ type: 'uniform',
+ minBindingSize: 4,
+ hasDynamicOffset: true,
+ },
+ },
+ ],
+ });
+ }
+
+ GetBindGroupForT2TCopyWithDepthTests(bindGroupLayout, totalCopyArrayLayers) {
+ // Prepare the uniform buffer that contains all the copy layers to generate different depth
+ // values for different copy layers.
+ assert(totalCopyArrayLayers > 0);
+ const uniformBufferSize = kMinDynamicBufferOffsetAlignment * (totalCopyArrayLayers - 1) + 4;
+ const uniformBufferData = new Float32Array(uniformBufferSize / 4);
+ for (let i = 1; i < totalCopyArrayLayers; ++i) {
+ uniformBufferData[(kMinDynamicBufferOffsetAlignment / 4) * i] = i;
+ }
+ const uniformBuffer = makeBufferWithContents(
+ this.device,
+ uniformBufferData,
+ GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM
+ );
+
+ return this.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ size: 4,
+ },
+ },
+ ],
+ });
+ }
+
+ /** Initialize the depth aspect of sourceTexture with draw calls */
+ InitializeDepthAspect(sourceTexture, depthFormat, srcCopyLevel, srcCopyBaseArrayLayer, copySize) {
+ // Prepare a renderPipeline with depthCompareFunction == 'always' and depthWriteEnabled == true
+ // for the initializations of the depth attachment.
+ const bindGroupLayout = this.GetBindGroupLayoutForT2TCopyWithDepthTests();
+ const renderPipeline = this.GetRenderPipelineForT2TCopyWithDepthTests(bindGroupLayout, false, {
+ format: depthFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'always',
+ });
+ const bindGroup = this.GetBindGroupForT2TCopyWithDepthTests(bindGroupLayout, copySize[2]);
+
+ const encoder = this.device.createCommandEncoder();
+ for (let srcCopyLayer = 0; srcCopyLayer < copySize[2]; ++srcCopyLayer) {
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: sourceTexture.createView({
+ baseArrayLayer: srcCopyLayer + srcCopyBaseArrayLayer,
+ arrayLayerCount: 1,
+ baseMipLevel: srcCopyLevel,
+ mipLevelCount: 1,
+ }),
+ depthClearValue: 0.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilLoadOp: 'load',
+ stencilStoreOp: 'store',
+ },
+ });
+ renderPass.setBindGroup(0, bindGroup, [srcCopyLayer * kMinDynamicBufferOffsetAlignment]);
+ renderPass.setPipeline(renderPipeline);
+ renderPass.draw(6);
+ renderPass.end();
+ }
+ this.queue.submit([encoder.finish()]);
+ }
+
+ VerifyDepthAspect(
+ destinationTexture,
+ depthFormat,
+ dstCopyLevel,
+ dstCopyBaseArrayLayer,
+ copySize
+ ) {
+ // Prepare a renderPipeline with depthCompareFunction == 'equal' and depthWriteEnabled == false
+ // for the comparison of the depth attachment.
+ const bindGroupLayout = this.GetBindGroupLayoutForT2TCopyWithDepthTests();
+ const renderPipeline = this.GetRenderPipelineForT2TCopyWithDepthTests(bindGroupLayout, true, {
+ format: depthFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'equal',
+ });
+ const bindGroup = this.GetBindGroupForT2TCopyWithDepthTests(bindGroupLayout, copySize[2]);
+
+ const outputColorTexture = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: copySize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ this.trackForCleanup(outputColorTexture);
+ const encoder = this.device.createCommandEncoder();
+ for (let dstCopyLayer = 0; dstCopyLayer < copySize[2]; ++dstCopyLayer) {
+ // If the depth value is not expected, the color of outputColorTexture will remain Red after
+ // the render pass.
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputColorTexture.createView({
+ baseArrayLayer: dstCopyLayer,
+ arrayLayerCount: 1,
+ }),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: destinationTexture.createView({
+ baseArrayLayer: dstCopyLayer + dstCopyBaseArrayLayer,
+ arrayLayerCount: 1,
+ baseMipLevel: dstCopyLevel,
+ mipLevelCount: 1,
+ }),
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilLoadOp: 'load',
+ stencilStoreOp: 'store',
+ },
+ });
+ renderPass.setBindGroup(0, bindGroup, [dstCopyLayer * kMinDynamicBufferOffsetAlignment]);
+ renderPass.setPipeline(renderPipeline);
+ renderPass.draw(6);
+ renderPass.end();
+ }
+ this.queue.submit([encoder.finish()]);
+
+ this.expectSingleColor(outputColorTexture, 'rgba8unorm', {
+ size: copySize,
+ exp: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ });
+ }
+}
+
+const kCopyBoxOffsetsForWholeDepth = [
+ // From (0, 0) of src to (0, 0) of dst.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (0, 0) of src to (blockWidth, 0) of dst.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 1, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (0, 0) of src to (0, blockHeight) of dst.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 1, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (blockWidth, 0) of src to (0, 0) of dst.
+ {
+ srcOffset: { x: 1, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (0, blockHeight) of src to (0, 0) of dst.
+ {
+ srcOffset: { x: 0, y: 1, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (blockWidth, 0) of src to (0, 0) of dst, and the copy extent will not cover the last
+ // texel block column of both source and destination texture.
+ {
+ srcOffset: { x: 1, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: -1, height: 0, depthOrArrayLayers: 0 },
+ },
+ // From (0, blockHeight) of src to (0, 0) of dst, and the copy extent will not cover the last
+ // texel block row of both source and destination texture.
+ {
+ srcOffset: { x: 0, y: 1, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: -1, depthOrArrayLayers: 0 },
+ },
+];
+
+const kCopyBoxOffsetsFor2DArrayTextures = [
+ // Copy the whole array slices from the source texture to the destination texture.
+ // The copy extent will cover the whole subresource of either source or the
+ // destination texture
+ ...kCopyBoxOffsetsForWholeDepth,
+
+ // Copy 1 texture slice from the 1st slice of the source texture to the 1st slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -2 },
+ },
+ // Copy 1 texture slice from the 2nd slice of the source texture to the 2nd slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 1 },
+ dstOffset: { x: 0, y: 0, z: 1 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -3 },
+ },
+ // Copy 1 texture slice from the 1st slice of the source texture to the 2nd slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 1 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -1 },
+ },
+ // Copy 1 texture slice from the 2nd slice of the source texture to the 1st slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 1 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -1 },
+ },
+ // Copy 2 texture slices from the 1st slice of the source texture to the 1st slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -3 },
+ },
+ // Copy 3 texture slices from the 2nd slice of the source texture to the 2nd slice of the
+ // destination texture.
+ {
+ srcOffset: { x: 0, y: 0, z: 1 },
+ dstOffset: { x: 0, y: 0, z: 1 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -1 },
+ },
+];
+
+export const g = makeTestGroup(F);
+
+g.test('color_textures,non_compressed,non_array')
+ .desc(
+ `
+ Validate the correctness of the copy by filling the srcTexture with testable data and any
+ non-compressed color format supported by WebGPU, doing CopyTextureToTexture() copy, and verifying
+ the content of the whole dstTexture.
+
+ Copy {1 texel block, part of, the whole} srcTexture to the dstTexture {with, without} a non-zero
+ valid srcOffset that
+ - covers the whole dstTexture subresource
+ - covers the corners of the dstTexture
+ - doesn't cover any texels that are on the edge of the dstTexture
+ - covers the mipmap level > 0
+
+ Tests for all pairs of valid source/destination formats, and all texture dimensions.
+ `
+ )
+ .params(u =>
+ u
+ .combine('srcFormat', kRegularTextureFormats)
+ .combine('dstFormat', kRegularTextureFormats)
+ .filter(({ srcFormat, dstFormat }) => {
+ const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat;
+ const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat;
+ return (
+ srcFormat === dstFormat ||
+ (srcBaseFormat !== undefined &&
+ dstBaseFormat !== undefined &&
+ srcBaseFormat === dstBaseFormat)
+ );
+ })
+ .combine('dimension', kTextureDimensions)
+ .filter(
+ ({ dimension, srcFormat, dstFormat }) =>
+ textureDimensionAndFormatCompatible(dimension, srcFormat) &&
+ textureDimensionAndFormatCompatible(dimension, dstFormat)
+ )
+ .beginSubcases()
+ .expandWithParams(p => {
+ const params = [
+ {
+ srcTextureSize: { width: 32, height: 32, depthOrArrayLayers: 1 },
+ dstTextureSize: { width: 32, height: 32, depthOrArrayLayers: 1 },
+ },
+ {
+ srcTextureSize: { width: 31, height: 33, depthOrArrayLayers: 1 },
+ dstTextureSize: { width: 31, height: 33, depthOrArrayLayers: 1 },
+ },
+ {
+ srcTextureSize: { width: 32, height: 32, depthOrArrayLayers: 1 },
+ dstTextureSize: { width: 64, height: 64, depthOrArrayLayers: 1 },
+ },
+ {
+ srcTextureSize: { width: 32, height: 32, depthOrArrayLayers: 1 },
+ dstTextureSize: { width: 63, height: 61, depthOrArrayLayers: 1 },
+ },
+ ];
+
+ if (p.dimension === '1d') {
+ for (const param of params) {
+ param.srcTextureSize.height = 1;
+ param.dstTextureSize.height = 1;
+ }
+ }
+
+ return params;
+ })
+ .combine('copyBoxOffsets', kCopyBoxOffsetsForWholeDepth)
+ .unless(
+ p =>
+ p.dimension === '1d' &&
+ (p.copyBoxOffsets.copyExtent.height !== 0 ||
+ p.copyBoxOffsets.srcOffset.y !== 0 ||
+ p.copyBoxOffsets.dstOffset.y !== 0)
+ )
+ .combine('srcCopyLevel', [0, 3])
+ .combine('dstCopyLevel', [0, 3])
+ .unless(p => p.dimension === '1d' && (p.srcCopyLevel !== 0 || p.dstCopyLevel !== 0))
+ )
+ .fn(async t => {
+ const {
+ dimension,
+ srcTextureSize,
+ dstTextureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel,
+ } = t.params;
+
+ t.DoCopyTextureToTextureTest(
+ dimension,
+ srcTextureSize,
+ dstTextureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel
+ );
+ });
+
+g.test('color_textures,compressed,non_array')
+ .desc(
+ `
+ Validate the correctness of the copy by filling the srcTexture with testable data and any
+ compressed color format supported by WebGPU, doing CopyTextureToTexture() copy, and verifying
+ the content of the whole dstTexture.
+
+ Tests for all pairs of valid source/destination formats, and all texture dimensions.
+ `
+ )
+ .params(u =>
+ u
+ .combine('srcFormat', kCompressedTextureFormats)
+ .combine('dstFormat', kCompressedTextureFormats)
+ .filter(({ srcFormat, dstFormat }) => {
+ const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat;
+ const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat;
+ return (
+ srcFormat === dstFormat ||
+ (srcBaseFormat !== undefined &&
+ dstBaseFormat !== undefined &&
+ srcBaseFormat === dstBaseFormat)
+ );
+ })
+ .combine('dimension', kTextureDimensions)
+ .filter(
+ ({ dimension, srcFormat, dstFormat }) =>
+ textureDimensionAndFormatCompatible(dimension, srcFormat) &&
+ textureDimensionAndFormatCompatible(dimension, dstFormat)
+ )
+ .beginSubcases()
+ .combine('textureSizeInBlocks', [
+ // The heights and widths in blocks are all power of 2
+ { src: { width: 16, height: 8 }, dst: { width: 16, height: 8 } },
+ // The virtual width of the source texture at mipmap level 2 (15) is not a multiple of 4 blocks
+ { src: { width: 15, height: 8 }, dst: { width: 16, height: 8 } },
+ // The virtual width of the destination texture at mipmap level 2 (15) is not a multiple
+ // of 4 blocks
+ { src: { width: 16, height: 8 }, dst: { width: 15, height: 8 } },
+ // The virtual height of the source texture at mipmap level 2 (13) is not a multiple of 4 blocks
+ { src: { width: 16, height: 13 }, dst: { width: 16, height: 8 } },
+ // The virtual height of the destination texture at mipmap level 2 (13) is not a
+ // multiple of 4 blocks
+ { src: { width: 16, height: 8 }, dst: { width: 16, height: 13 } },
+ // None of the widths or heights in blocks are power of 2
+ { src: { width: 15, height: 13 }, dst: { width: 15, height: 13 } },
+ ])
+ .combine('copyBoxOffsets', kCopyBoxOffsetsForWholeDepth)
+ .combine('srcCopyLevel', [0, 2])
+ .combine('dstCopyLevel', [0, 2])
+ )
+ .beforeAllSubcases(t => {
+ const { srcFormat, dstFormat } = t.params;
+ t.selectDeviceOrSkipTestCase([
+ kTextureFormatInfo[srcFormat].feature,
+ kTextureFormatInfo[dstFormat].feature,
+ ]);
+ })
+ .fn(async t => {
+ const {
+ dimension,
+ textureSizeInBlocks,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel,
+ } = t.params;
+ const srcBlockWidth = kTextureFormatInfo[srcFormat].blockWidth;
+ const srcBlockHeight = kTextureFormatInfo[srcFormat].blockHeight;
+ const dstBlockWidth = kTextureFormatInfo[dstFormat].blockWidth;
+ const dstBlockHeight = kTextureFormatInfo[dstFormat].blockHeight;
+
+ t.DoCopyTextureToTextureTest(
+ dimension,
+ {
+ width: textureSizeInBlocks.src.width * srcBlockWidth,
+ height: textureSizeInBlocks.src.height * srcBlockHeight,
+ depthOrArrayLayers: 1,
+ },
+ {
+ width: textureSizeInBlocks.dst.width * dstBlockWidth,
+ height: textureSizeInBlocks.dst.height * dstBlockHeight,
+ depthOrArrayLayers: 1,
+ },
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel
+ );
+ });
+
+g.test('color_textures,non_compressed,array')
+ .desc(
+ `
+ Validate the correctness of the texture-to-texture copy on 2D array textures by filling the
+ srcTexture with testable data and any non-compressed color format supported by WebGPU, doing
+ CopyTextureToTexture() copy, and verifying the content of the whole dstTexture.
+ `
+ )
+ .params(u =>
+ u
+ .combine('srcFormat', kRegularTextureFormats)
+ .combine('dstFormat', kRegularTextureFormats)
+ .filter(({ srcFormat, dstFormat }) => {
+ const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat;
+ const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat;
+ return (
+ srcFormat === dstFormat ||
+ (srcBaseFormat !== undefined &&
+ dstBaseFormat !== undefined &&
+ srcBaseFormat === dstBaseFormat)
+ );
+ })
+ .combine('dimension', ['2d', '3d'])
+ .filter(
+ ({ dimension, srcFormat, dstFormat }) =>
+ textureDimensionAndFormatCompatible(dimension, srcFormat) &&
+ textureDimensionAndFormatCompatible(dimension, dstFormat)
+ )
+ .beginSubcases()
+ .combine('textureSize', [
+ {
+ srcTextureSize: { width: 64, height: 32, depthOrArrayLayers: 5 },
+ dstTextureSize: { width: 64, height: 32, depthOrArrayLayers: 5 },
+ },
+ {
+ srcTextureSize: { width: 31, height: 33, depthOrArrayLayers: 5 },
+ dstTextureSize: { width: 31, height: 33, depthOrArrayLayers: 5 },
+ },
+ {
+ srcTextureSize: { width: 31, height: 32, depthOrArrayLayers: 33 },
+ dstTextureSize: { width: 31, height: 32, depthOrArrayLayers: 33 },
+ },
+ ])
+ .combine('copyBoxOffsets', kCopyBoxOffsetsFor2DArrayTextures)
+ .combine('srcCopyLevel', [0, 3])
+ .combine('dstCopyLevel', [0, 3])
+ )
+ .fn(async t => {
+ const {
+ dimension,
+ textureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel,
+ } = t.params;
+
+ t.DoCopyTextureToTextureTest(
+ dimension,
+ textureSize.srcTextureSize,
+ textureSize.dstTextureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel
+ );
+ });
+
+g.test('color_textures,compressed,array')
+ .desc(
+ `
+ Validate the correctness of the texture-to-texture copy on 2D array textures by filling the
+ srcTexture with testable data and any compressed color format supported by WebGPU, doing
+ CopyTextureToTexture() copy, and verifying the content of the whole dstTexture.
+
+ Tests for all pairs of valid source/destination formats, and all texture dimensions.
+ `
+ )
+ .params(u =>
+ u
+ .combine('srcFormat', kCompressedTextureFormats)
+ .combine('dstFormat', kCompressedTextureFormats)
+ .filter(({ srcFormat, dstFormat }) => {
+ const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat;
+ const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat;
+ return (
+ srcFormat === dstFormat ||
+ (srcBaseFormat !== undefined &&
+ dstBaseFormat !== undefined &&
+ srcBaseFormat === dstBaseFormat)
+ );
+ })
+ .combine('dimension', ['2d', '3d'])
+ .filter(
+ ({ dimension, srcFormat, dstFormat }) =>
+ textureDimensionAndFormatCompatible(dimension, srcFormat) &&
+ textureDimensionAndFormatCompatible(dimension, dstFormat)
+ )
+ .beginSubcases()
+ .combine('textureSizeInBlocks', [
+ // The heights and widths in blocks are all power of 2
+ { src: { width: 2, height: 2 }, dst: { width: 2, height: 2 } },
+ // None of the widths or heights in blocks are power of 2
+ { src: { width: 15, height: 13 }, dst: { width: 15, height: 13 } },
+ ])
+ .combine('copyBoxOffsets', kCopyBoxOffsetsFor2DArrayTextures)
+ .combine('srcCopyLevel', [0, 2])
+ .combine('dstCopyLevel', [0, 2])
+ )
+ .beforeAllSubcases(t => {
+ const { srcFormat, dstFormat } = t.params;
+
+ t.selectDeviceOrSkipTestCase([
+ kTextureFormatInfo[srcFormat].feature,
+ kTextureFormatInfo[dstFormat].feature,
+ ]);
+ })
+ .fn(async t => {
+ const {
+ dimension,
+ textureSizeInBlocks,
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel,
+ } = t.params;
+ const srcBlockWidth = kTextureFormatInfo[srcFormat].blockWidth;
+ const srcBlockHeight = kTextureFormatInfo[srcFormat].blockHeight;
+ const dstBlockWidth = kTextureFormatInfo[dstFormat].blockWidth;
+ const dstBlockHeight = kTextureFormatInfo[dstFormat].blockHeight;
+
+ t.DoCopyTextureToTextureTest(
+ dimension,
+ {
+ width: textureSizeInBlocks.src.width * srcBlockWidth,
+ height: textureSizeInBlocks.src.height * srcBlockHeight,
+ depthOrArrayLayers: 5,
+ },
+ {
+ width: textureSizeInBlocks.dst.width * dstBlockWidth,
+ height: textureSizeInBlocks.dst.height * dstBlockHeight,
+ depthOrArrayLayers: 5,
+ },
+ srcFormat,
+ dstFormat,
+ copyBoxOffsets,
+ srcCopyLevel,
+ dstCopyLevel
+ );
+ });
+
+g.test('zero_sized')
+ .desc(
+ `
+ Validate the correctness of zero-sized copies (should be no-ops).
+
+ - For each texture dimension.
+ - Copies that are zero-sized in only one dimension {x, y, z}, each touching the {lower, upper} end
+ of that dimension.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combineWithParams([
+ { dimension: '1d', textureSize: { width: 32, height: 1, depthOrArrayLayers: 1 } },
+ { dimension: '2d', textureSize: { width: 32, height: 32, depthOrArrayLayers: 5 } },
+ { dimension: '3d', textureSize: { width: 32, height: 32, depthOrArrayLayers: 5 } },
+ ])
+ .combine('copyBoxOffset', [
+ // copyExtent.width === 0
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: -64, height: 0, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.width === 0 && srcOffset.x === textureWidth
+ {
+ srcOffset: { x: 64, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: -64, height: 0, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.width === 0 && dstOffset.x === textureWidth
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 64, y: 0, z: 0 },
+ copyExtent: { width: -64, height: 0, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.height === 0
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: -32, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.height === 0 && srcOffset.y === textureHeight
+ {
+ srcOffset: { x: 0, y: 32, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: -32, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.height === 0 && dstOffset.y === textureHeight
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 32, z: 0 },
+ copyExtent: { width: 0, height: -32, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.depthOrArrayLayers === 0
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: -5 },
+ },
+ // copyExtent.depthOrArrayLayers === 0 && srcOffset.z === textureDepth
+ {
+ srcOffset: { x: 0, y: 0, z: 5 },
+ dstOffset: { x: 0, y: 0, z: 0 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ // copyExtent.depthOrArrayLayers === 0 && dstOffset.z === textureDepth
+ {
+ srcOffset: { x: 0, y: 0, z: 0 },
+ dstOffset: { x: 0, y: 0, z: 5 },
+ copyExtent: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ },
+ ])
+ .unless(
+ p =>
+ p.dimension === '1d' &&
+ (p.copyBoxOffset.copyExtent.height !== 0 ||
+ p.copyBoxOffset.srcOffset.y !== 0 ||
+ p.copyBoxOffset.dstOffset.y !== 0)
+ )
+ .combine('srcCopyLevel', [0, 3])
+ .combine('dstCopyLevel', [0, 3])
+ .unless(p => p.dimension === '1d' && (p.srcCopyLevel !== 0 || p.dstCopyLevel !== 0))
+ )
+ .fn(async t => {
+ const { dimension, textureSize, copyBoxOffset, srcCopyLevel, dstCopyLevel } = t.params;
+
+ const srcFormat = 'rgba8unorm';
+ const dstFormat = 'rgba8unorm';
+
+ t.DoCopyTextureToTextureTest(
+ dimension,
+ textureSize,
+ textureSize,
+ srcFormat,
+ dstFormat,
+ copyBoxOffset,
+ srcCopyLevel,
+ dstCopyLevel
+ );
+ });
+
+g.test('copy_depth_stencil')
+ .desc(
+ `
+ Validate the correctness of copyTextureToTexture() with depth and stencil aspect.
+
+ For all the texture formats with stencil aspect:
+ - Initialize the stencil aspect of the source texture with writeTexture().
+ - Copy the stencil aspect from the source texture into the destination texture
+ - Copy the stencil aspect of the destination texture into another staging buffer and check its
+ content
+ - Test the copies from / into zero / non-zero array layer / mipmap levels
+ - Test copying multiple array layers
+
+ For all the texture formats with depth aspect:
+ - Initialize the depth aspect of the source texture with a draw call
+ - Copy the depth aspect from the source texture into the destination texture
+ - Validate the content in the destination texture with the depth comparison function 'equal'
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('srcTextureSize', [
+ { width: 32, height: 16, depthOrArrayLayers: 1 },
+ { width: 32, height: 16, depthOrArrayLayers: 4 },
+ { width: 24, height: 48, depthOrArrayLayers: 5 },
+ ])
+ .combine('srcCopyLevel', [0, 2])
+ .combine('dstCopyLevel', [0, 2])
+ .combine('srcCopyBaseArrayLayer', [0, 1])
+ .combine('dstCopyBaseArrayLayer', [0, 1])
+ .filter(t => {
+ return (
+ t.srcTextureSize.depthOrArrayLayers > t.srcCopyBaseArrayLayer &&
+ t.srcTextureSize.depthOrArrayLayers > t.dstCopyBaseArrayLayer
+ );
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const {
+ format,
+ srcTextureSize,
+ srcCopyLevel,
+ dstCopyLevel,
+ srcCopyBaseArrayLayer,
+ dstCopyBaseArrayLayer,
+ } = t.params;
+
+ const copySize = [
+ srcTextureSize.width >> srcCopyLevel,
+ srcTextureSize.height >> srcCopyLevel,
+ srcTextureSize.depthOrArrayLayers - Math.max(srcCopyBaseArrayLayer, dstCopyBaseArrayLayer),
+ ];
+
+ const sourceTexture = t.device.createTexture({
+ format,
+ size: srcTextureSize,
+ usage:
+ GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ mipLevelCount: srcCopyLevel + 1,
+ });
+ t.trackForCleanup(sourceTexture);
+ const destinationTexture = t.device.createTexture({
+ format,
+ size: [
+ copySize[0] << dstCopyLevel,
+ copySize[1] << dstCopyLevel,
+ srcTextureSize.depthOrArrayLayers,
+ ],
+
+ usage:
+ GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ mipLevelCount: dstCopyLevel + 1,
+ });
+ t.trackForCleanup(destinationTexture);
+
+ let initialStencilData = undefined;
+ if (kTextureFormatInfo[format].stencil) {
+ initialStencilData = t.GetInitialStencilDataPerMipLevel(srcTextureSize, format, srcCopyLevel);
+ t.InitializeStencilAspect(
+ sourceTexture,
+ initialStencilData,
+ srcCopyLevel,
+ srcCopyBaseArrayLayer,
+ copySize
+ );
+ }
+ if (kTextureFormatInfo[format].depth) {
+ t.InitializeDepthAspect(sourceTexture, format, srcCopyLevel, srcCopyBaseArrayLayer, copySize);
+ }
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyTextureToTexture(
+ {
+ texture: sourceTexture,
+ mipLevel: srcCopyLevel,
+ origin: { x: 0, y: 0, z: srcCopyBaseArrayLayer },
+ },
+ {
+ texture: destinationTexture,
+ mipLevel: dstCopyLevel,
+ origin: { x: 0, y: 0, z: dstCopyBaseArrayLayer },
+ },
+ copySize
+ );
+
+ t.queue.submit([encoder.finish()]);
+
+ if (kTextureFormatInfo[format].stencil) {
+ assert(initialStencilData !== undefined);
+ t.VerifyStencilAspect(
+ destinationTexture,
+ initialStencilData,
+ dstCopyLevel,
+ dstCopyBaseArrayLayer,
+ copySize
+ );
+ }
+ if (kTextureFormatInfo[format].depth) {
+ t.VerifyDepthAspect(
+ destinationTexture,
+ format,
+ dstCopyLevel,
+ dstCopyBaseArrayLayer,
+ copySize
+ );
+ }
+ });
+
+g.test('copy_multisampled_color')
+ .desc(
+ `
+ Validate the correctness of copyTextureToTexture() with multisampled color formats.
+
+ - Initialize the source texture with a triangle in a render pass.
+ - Copy from the source texture into the destination texture with CopyTextureToTexture().
+ - Compare every sub-pixel of source texture and destination texture in another render pass:
+ - If they are different, then output RED; otherwise output GREEN
+ - Verify the pixels in the output texture are all GREEN.
+ - Note that in current WebGPU SPEC the mipmap level count and array layer count of a multisampled
+ texture can only be 1.
+ `
+ )
+ .fn(async t => {
+ const textureSize = [32, 16, 1];
+ const kColorFormat = 'rgba8unorm';
+ const kSampleCount = 4;
+
+ const sourceTexture = t.device.createTexture({
+ format: kColorFormat,
+ size: textureSize,
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: kSampleCount,
+ });
+ t.trackForCleanup(sourceTexture);
+ const destinationTexture = t.device.createTexture({
+ format: kColorFormat,
+ size: textureSize,
+ usage:
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: kSampleCount,
+ });
+ t.trackForCleanup(destinationTexture);
+
+ // Initialize sourceTexture with a draw call.
+ const renderPipelineForInit = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0)
+ );
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.3, 0.5, 0.8, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: kColorFormat }],
+ },
+ multisample: {
+ count: kSampleCount,
+ },
+ });
+ const initEncoder = t.device.createCommandEncoder();
+ const renderPassForInit = initEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: sourceTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPassForInit.setPipeline(renderPipelineForInit);
+ renderPassForInit.draw(3);
+ renderPassForInit.end();
+ t.queue.submit([initEncoder.finish()]);
+
+ // Do the texture-to-texture copy
+ const copyEncoder = t.device.createCommandEncoder();
+ copyEncoder.copyTextureToTexture(
+ {
+ texture: sourceTexture,
+ },
+ {
+ texture: destinationTexture,
+ },
+ textureSize
+ );
+
+ t.queue.submit([copyEncoder.finish()]);
+
+ // Verify if all the sub-pixel values at the same location of sourceTexture and
+ // destinationTexture are equal.
+ const renderPipelineForValidation = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var sourceTexture : texture_multisampled_2d<f32>;
+ @group(0) @binding(1) var destinationTexture : texture_multisampled_2d<f32>;
+ @fragment
+ fn main(@builtin(position) coord_in: vec4<f32>) -> @location(0) vec4<f32> {
+ var coord_in_vec2 = vec2<i32>(i32(coord_in.x), i32(coord_in.y));
+ for (var sampleIndex = 0; sampleIndex < ${kSampleCount};
+ sampleIndex = sampleIndex + 1) {
+ var sourceSubPixel : vec4<f32> =
+ textureLoad(sourceTexture, coord_in_vec2, sampleIndex);
+ var destinationSubPixel : vec4<f32> =
+ textureLoad(destinationTexture, coord_in_vec2, sampleIndex);
+ if (!all(sourceSubPixel == destinationSubPixel)) {
+ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ }
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: kColorFormat }],
+ },
+ });
+ const bindGroup = t.device.createBindGroup({
+ layout: renderPipelineForValidation.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: sourceTexture.createView(),
+ },
+ {
+ binding: 1,
+ resource: destinationTexture.createView(),
+ },
+ ],
+ });
+ const expectedOutputTexture = t.device.createTexture({
+ format: kColorFormat,
+ size: textureSize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(expectedOutputTexture);
+ const validationEncoder = t.device.createCommandEncoder();
+ const renderPassForValidation = validationEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: expectedOutputTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPassForValidation.setPipeline(renderPipelineForValidation);
+ renderPassForValidation.setBindGroup(0, bindGroup);
+ renderPassForValidation.draw(6);
+ renderPassForValidation.end();
+ t.queue.submit([validationEncoder.finish()]);
+
+ t.expectSingleColor(expectedOutputTexture, 'rgba8unorm', {
+ size: [textureSize[0], textureSize[1], textureSize[2]],
+ exp: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ });
+ });
+
+g.test('copy_multisampled_depth')
+ .desc(
+ `
+ Validate the correctness of copyTextureToTexture() with multisampled depth formats.
+
+ - Initialize the source texture with a triangle in a render pass.
+ - Copy from the source texture into the destination texture with CopyTextureToTexture().
+ - Validate the content in the destination texture with the depth comparison function 'equal'.
+ - Note that in current WebGPU SPEC the mipmap level count and array layer count of a multisampled
+ texture can only be 1.
+ `
+ )
+ .fn(async t => {
+ const textureSize = [32, 16, 1];
+ const kDepthFormat = 'depth24plus';
+ const kSampleCount = 4;
+
+ const sourceTexture = t.device.createTexture({
+ format: kDepthFormat,
+ size: textureSize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: kSampleCount,
+ });
+ t.trackForCleanup(sourceTexture);
+ const destinationTexture = t.device.createTexture({
+ format: kDepthFormat,
+ size: textureSize,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: kSampleCount,
+ });
+ t.trackForCleanup(destinationTexture);
+
+ const vertexState = {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)-> @builtin(position) vec4<f32> {
+ var pos : array<vec3<f32>, 6> = array<vec3<f32>, 6>(
+ vec3<f32>(-1.0, 1.0, 0.5),
+ vec3<f32>(-1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, 1.0, 1.0),
+ vec3<f32>(-1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, 1.0, 1.0),
+ vec3<f32>( 1.0, -1.0, 0.5));
+ return vec4<f32>(pos[VertexIndex], 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ };
+
+ // Initialize the depth aspect of source texture with a draw call
+ const renderPipelineForInit = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: vertexState,
+ depthStencil: {
+ format: kDepthFormat,
+ depthCompare: 'always',
+ depthWriteEnabled: true,
+ },
+ multisample: {
+ count: kSampleCount,
+ },
+ });
+
+ const encoderForInit = t.device.createCommandEncoder();
+ const renderPassForInit = encoderForInit.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: sourceTexture.createView(),
+ depthClearValue: 0.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ },
+ });
+ renderPassForInit.setPipeline(renderPipelineForInit);
+ renderPassForInit.draw(6);
+ renderPassForInit.end();
+ t.queue.submit([encoderForInit.finish()]);
+
+ // Do the texture-to-texture copy
+ const copyEncoder = t.device.createCommandEncoder();
+ copyEncoder.copyTextureToTexture(
+ {
+ texture: sourceTexture,
+ },
+ {
+ texture: destinationTexture,
+ },
+ textureSize
+ );
+
+ t.queue.submit([copyEncoder.finish()]);
+
+ // Verify the depth values in destinationTexture are what we expected with
+ // depthCompareFunction == 'equal' and depthWriteEnabled == false in the render pipeline
+ const kColorFormat = 'rgba8unorm';
+ const renderPipelineForVerify = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: vertexState,
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: kColorFormat }],
+ },
+ depthStencil: {
+ format: kDepthFormat,
+ depthCompare: 'equal',
+ depthWriteEnabled: false,
+ },
+ multisample: {
+ count: kSampleCount,
+ },
+ });
+ const multisampledColorTexture = t.device.createTexture({
+ format: kColorFormat,
+ size: textureSize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: kSampleCount,
+ });
+ t.trackForCleanup(multisampledColorTexture);
+ const colorTextureAsResolveTarget = t.device.createTexture({
+ format: kColorFormat,
+ size: textureSize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(colorTextureAsResolveTarget);
+
+ const encoderForVerify = t.device.createCommandEncoder();
+ const renderPassForVerify = encoderForVerify.beginRenderPass({
+ colorAttachments: [
+ {
+ view: multisampledColorTexture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'discard',
+ resolveTarget: colorTextureAsResolveTarget.createView(),
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: destinationTexture.createView(),
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ },
+ });
+ renderPassForVerify.setPipeline(renderPipelineForVerify);
+ renderPassForVerify.draw(6);
+ renderPassForVerify.end();
+ t.queue.submit([encoderForVerify.finish()]);
+
+ t.expectSingleColor(colorTextureAsResolveTarget, kColorFormat, {
+ size: [textureSize[0], textureSize[1], textureSize[2]],
+ exp: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js
new file mode 100644
index 0000000000..bfba8c63b5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/image_copy.spec.js
@@ -0,0 +1,1910 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `writeTexture + copyBufferToTexture + copyTextureToBuffer operation tests.
+
+* copy_with_various_rows_per_image_and_bytes_per_row: test that copying data with various bytesPerRow (including { ==, > } bytesInACompleteRow) and\
+ rowsPerImage (including { ==, > } copyExtent.height) values and minimum required bytes in copy works for every format. Also covers special code paths:
+ - bufferSize - offset < bytesPerImage * copyExtent.depthOrArrayLayers
+ - when bytesPerRow is not a multiple of 512 and copyExtent.depthOrArrayLayers > 1: copyExtent.depthOrArrayLayers % 2 == { 0, 1 }
+ - bytesPerRow == bytesInACompleteCopyImage
+
+* copy_with_various_offsets_and_data_sizes: test that copying data with various offset (including { ==, > } 0 and is/isn't power of 2) values and additional\
+ data paddings works for every format with 2d and 2d-array textures. Also covers special code paths:
+ - offset + bytesInCopyExtentPerRow { ==, > } bytesPerRow
+ - offset > bytesInACompleteCopyImage
+
+* copy_with_various_origins_and_copy_extents: test that copying slices of a texture works with various origin (including { origin.x, origin.y, origin.z }\
+ { ==, > } 0 and is/isn't power of 2) and copyExtent (including { copyExtent.x, copyExtent.y, copyExtent.z } { ==, > } 0 and is/isn't power of 2) values\
+ (also including {origin._ + copyExtent._ { ==, < } the subresource size of textureCopyView) works for all formats. origin and copyExtent values are passed\
+ as [number, number, number] instead of GPUExtent3DDict.
+
+* copy_various_mip_levels: test that copying various mip levels works for all formats. Also covers special code paths:
+ - the physical size of the subresource is not equal to the logical size
+ - bufferSize - offset < bytesPerImage * copyExtent.depthOrArrayLayers and copyExtent needs to be clamped
+
+* copy_with_no_image_or_slice_padding_and_undefined_values: test that when copying a single row we can set any bytesPerRow value and when copying a single\
+ slice we can set rowsPerImage to 0. Also test setting offset, rowsPerImage, mipLevel, origin, origin.{x,y,z} to undefined.
+
+* TODO:
+ - add another initMethod which renders the texture [3]
+ - test copyT2B with buffer size not divisible by 4 (not done because expectContents 4-byte alignment)
+ - Convert the float32 values in initialData into the ones compatible to the depth aspect of
+ depthFormats when depth16unorm is supported by the browsers in
+ DoCopyTextureToBufferWithDepthAspectTest().
+
+TODO: Expand tests of GPUExtent3D [1]
+
+TODO: Fix this test for the various skipped formats [2]:
+- snorm tests failing due to rounding
+- float tests failing because float values are not byte-preserved
+- compressed formats
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, memcpy, unreachable } from '../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kDepthStencilFormats,
+ kMinDynamicBufferOffsetAlignment,
+ kBufferSizeAlignment,
+ depthStencilBufferTextureCopySupported,
+ depthStencilFormatAspectSize,
+ kTextureDimensions,
+ textureDimensionAndFormatCompatible,
+ kColorTextureFormats,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { makeBufferWithContents } from '../../../util/buffer.js';
+import { align } from '../../../util/math.js';
+import { DataArrayGenerator } from '../../../util/texture/data_generation.js';
+import {
+ bytesInACompleteRow,
+ dataBytesForCopyOrFail,
+ getTextureCopyLayout,
+ kBytesPerRowAlignment,
+} from '../../../util/texture/layout.js';
+
+/** Each combination of methods assume that the ones before it were tested and work correctly. */
+const kMethodsToTest = [
+ // Then we make sure that WriteTexture works for all formats:
+ { initMethod: 'WriteTexture', checkMethod: 'FullCopyT2B' },
+ // Then we make sure that CopyB2T works for all formats:
+ { initMethod: 'CopyB2T', checkMethod: 'FullCopyT2B' },
+ // Then we make sure that CopyT2B works for all formats:
+ { initMethod: 'WriteTexture', checkMethod: 'PartialCopyT2B' },
+];
+
+// [2]: Fix things so this list can be reduced to zero (see file description)
+const kExcludedFormats = new Set([
+ 'r8snorm',
+ 'rg8snorm',
+ 'rgba8snorm',
+ 'rg11b10ufloat',
+ 'rg16float',
+ 'rgba16float',
+ 'r32float',
+ 'rg32float',
+ 'rgba32float',
+]);
+
+const kWorkingColorTextureFormats = kColorTextureFormats.filter(x => !kExcludedFormats.has(x));
+
+const dataGenerator = new DataArrayGenerator();
+const altDataGenerator = new DataArrayGenerator();
+
+class ImageCopyTest extends GPUTest {
+ /** Offset for a particular texel in the linear texture data */
+ getTexelOffsetInBytes(textureDataLayout, format, texel, origin = { x: 0, y: 0, z: 0 }) {
+ const { offset, bytesPerRow, rowsPerImage } = textureDataLayout;
+ const info = kTextureFormatInfo[format];
+
+ assert(texel.x >= origin.x && texel.y >= origin.y && texel.z >= origin.z);
+ assert(texel.x % info.blockWidth === 0);
+ assert(texel.y % info.blockHeight === 0);
+ assert(origin.x % info.blockWidth === 0);
+ assert(origin.y % info.blockHeight === 0);
+
+ const bytesPerImage = rowsPerImage * bytesPerRow;
+
+ return (
+ offset +
+ (texel.z - origin.z) * bytesPerImage +
+ ((texel.y - origin.y) / info.blockHeight) * bytesPerRow +
+ ((texel.x - origin.x) / info.blockWidth) * info.bytesPerBlock
+ );
+ }
+
+ *iterateBlockRows(size, origin, format) {
+ if (size.width === 0 || size.height === 0 || size.depthOrArrayLayers === 0) {
+ // do not iterate anything for an empty region
+ return;
+ }
+ const info = kTextureFormatInfo[format];
+ assert(size.height % info.blockHeight === 0);
+ for (let y = 0; y < size.height; y += info.blockHeight) {
+ for (let z = 0; z < size.depthOrArrayLayers; ++z) {
+ yield {
+ x: origin.x,
+ y: origin.y + y,
+ z: origin.z + z,
+ };
+ }
+ }
+ }
+
+ /**
+ * This is used for testing passing undefined members of `GPUImageDataLayout` instead of actual
+ * values where possible. Passing arguments as values and not as objects so that they are passed
+ * by copy and not by reference.
+ */
+ undefDataLayoutIfNeeded(offset, rowsPerImage, bytesPerRow, changeBeforePass) {
+ if (changeBeforePass === 'undefined') {
+ if (offset === 0) {
+ offset = undefined;
+ }
+ if (bytesPerRow === 0) {
+ bytesPerRow = undefined;
+ }
+ if (rowsPerImage === 0) {
+ rowsPerImage = undefined;
+ }
+ }
+ return { offset, bytesPerRow, rowsPerImage };
+ }
+
+ /**
+ * This is used for testing passing undefined members of `GPUImageCopyTexture` instead of actual
+ * values where possible and also for testing passing the origin as `[number, number, number]`.
+ * Passing arguments as values and not as objects so that they are passed by copy and not by
+ * reference.
+ */
+ undefOrArrayCopyViewIfNeeded(texture, origin_x, origin_y, origin_z, mipLevel, changeBeforePass) {
+ let origin = { x: origin_x, y: origin_y, z: origin_z };
+
+ if (changeBeforePass === 'undefined') {
+ if (origin_x === 0 && origin_y === 0 && origin_z === 0) {
+ origin = undefined;
+ } else {
+ if (origin_x === 0) {
+ origin_x = undefined;
+ }
+ if (origin_y === 0) {
+ origin_y = undefined;
+ }
+ if (origin_z === 0) {
+ origin_z = undefined;
+ }
+ origin = { x: origin_x, y: origin_y, z: origin_z };
+ }
+
+ if (mipLevel === 0) {
+ mipLevel = undefined;
+ }
+ }
+
+ if (changeBeforePass === 'arrays') {
+ origin = [origin_x, origin_y, origin_z];
+ }
+
+ return { texture, origin, mipLevel };
+ }
+
+ /**
+ * This is used for testing passing `GPUExtent3D` as `[number, number, number]` instead of
+ * `GPUExtent3DDict`. Passing arguments as values and not as objects so that they are passed by
+ * copy and not by reference.
+ */
+ arrayCopySizeIfNeeded(width, height, depthOrArrayLayers, changeBeforePass) {
+ if (changeBeforePass === 'arrays') {
+ return [width, height, depthOrArrayLayers];
+ } else {
+ return { width, height, depthOrArrayLayers };
+ }
+ }
+
+ /** Run a CopyT2B command with appropriate arguments corresponding to `ChangeBeforePass` */
+ copyTextureToBufferWithAppliedArguments(
+ buffer,
+ { offset, rowsPerImage, bytesPerRow },
+ { width, height, depthOrArrayLayers },
+ { texture, mipLevel, origin },
+ changeBeforePass
+ ) {
+ const { x, y, z } = origin;
+
+ const appliedCopyView = this.undefOrArrayCopyViewIfNeeded(
+ texture,
+ x,
+ y,
+ z,
+ mipLevel,
+ changeBeforePass
+ );
+
+ const appliedDataLayout = this.undefDataLayoutIfNeeded(
+ offset,
+ rowsPerImage,
+ bytesPerRow,
+ changeBeforePass
+ );
+
+ const appliedCheckSize = this.arrayCopySizeIfNeeded(
+ width,
+ height,
+ depthOrArrayLayers,
+ changeBeforePass
+ );
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToBuffer(
+ appliedCopyView,
+ { buffer, ...appliedDataLayout },
+ appliedCheckSize
+ );
+
+ this.device.queue.submit([encoder.finish()]);
+ }
+
+ /** Put data into a part of the texture with an appropriate method. */
+ uploadLinearTextureDataToTextureSubBox(
+ textureCopyView,
+ textureDataLayout,
+ copySize,
+ partialData,
+ method,
+ changeBeforePass
+ ) {
+ const { texture, mipLevel, origin } = textureCopyView;
+ const { offset, rowsPerImage, bytesPerRow } = textureDataLayout;
+ const { x, y, z } = origin;
+ const { width, height, depthOrArrayLayers } = copySize;
+
+ const appliedCopyView = this.undefOrArrayCopyViewIfNeeded(
+ texture,
+ x,
+ y,
+ z,
+ mipLevel,
+ changeBeforePass
+ );
+
+ const appliedDataLayout = this.undefDataLayoutIfNeeded(
+ offset,
+ rowsPerImage,
+ bytesPerRow,
+ changeBeforePass
+ );
+
+ const appliedCopySize = this.arrayCopySizeIfNeeded(
+ width,
+ height,
+ depthOrArrayLayers,
+ changeBeforePass
+ );
+
+ switch (method) {
+ case 'WriteTexture': {
+ this.device.queue.writeTexture(
+ appliedCopyView,
+ partialData,
+ appliedDataLayout,
+ appliedCopySize
+ );
+
+ break;
+ }
+ case 'CopyB2T': {
+ const buffer = this.makeBufferWithContents(partialData, GPUBufferUsage.COPY_SRC);
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyBufferToTexture(
+ { buffer, ...appliedDataLayout },
+ appliedCopyView,
+ appliedCopySize
+ );
+
+ this.device.queue.submit([encoder.finish()]);
+
+ break;
+ }
+ default:
+ unreachable();
+ }
+ }
+
+ /**
+ * We check an appropriate part of the texture against the given data.
+ * Used directly with PartialCopyT2B check method (for a subpart of the texture)
+ * and by `copyWholeTextureToBufferAndCheckContentsWithUpdatedData` with FullCopyT2B check method
+ * (for the whole texture). We also ensure that CopyT2B doesn't overwrite bytes it's not supposed
+ * to if validateOtherBytesInBuffer is set to true.
+ */
+ copyPartialTextureToBufferAndCheckContents(
+ { texture, mipLevel, origin },
+ checkSize,
+ format,
+ expected,
+ expectedDataLayout,
+ changeBeforePass = 'none'
+ ) {
+ // The alignment is necessary because we need to copy and map data from this buffer.
+ const bufferSize = align(expected.byteLength, 4);
+ // The start value ensures generated data here doesn't match the expected data.
+ const bufferData = altDataGenerator.generateAndCopyView(bufferSize, 17);
+
+ const buffer = this.makeBufferWithContents(
+ bufferData,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ this.copyTextureToBufferWithAppliedArguments(
+ buffer,
+ expectedDataLayout,
+ checkSize,
+ { texture, mipLevel, origin },
+ changeBeforePass
+ );
+
+ this.updateLinearTextureDataSubBox(
+ expectedDataLayout,
+ expectedDataLayout,
+ checkSize,
+ origin,
+ origin,
+ format,
+ bufferData,
+ expected
+ );
+
+ this.expectGPUBufferValuesEqual(buffer, bufferData);
+ }
+
+ /**
+ * Copies the whole texture into linear data stored in a buffer for further checks.
+ *
+ * Used for `copyWholeTextureToBufferAndCheckContentsWithUpdatedData`.
+ */
+ copyWholeTextureToNewBuffer({ texture, mipLevel }, resultDataLayout) {
+ const { mipSize, byteLength, bytesPerRow, rowsPerImage } = resultDataLayout;
+ const buffer = this.device.createBuffer({
+ size: align(byteLength, 4), // this is necessary because we need to copy and map data from this buffer
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(buffer);
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToBuffer(
+ { texture, mipLevel },
+ { buffer, bytesPerRow, rowsPerImage },
+ mipSize
+ );
+
+ this.device.queue.submit([encoder.finish()]);
+
+ return buffer;
+ }
+
+ /**
+ * Takes the data returned by `copyWholeTextureToNewBuffer` and updates it after a copy operation
+ * on the texture by emulating the copy behaviour here directly.
+ */
+ updateLinearTextureDataSubBox(
+ destinationDataLayout,
+ sourceDataLayout,
+ copySize,
+ destinationOrigin,
+ sourceOrigin,
+ format,
+ destination,
+ source
+ ) {
+ for (const texel of this.iterateBlockRows(copySize, sourceOrigin, format)) {
+ const srcOffsetElements = this.getTexelOffsetInBytes(
+ sourceDataLayout,
+ format,
+ texel,
+ sourceOrigin
+ );
+
+ const dstOffsetElements = this.getTexelOffsetInBytes(
+ destinationDataLayout,
+ format,
+ texel,
+ destinationOrigin
+ );
+
+ const rowLength = bytesInACompleteRow(copySize.width, format);
+ memcpy(
+ { src: source, start: srcOffsetElements, length: rowLength },
+ { dst: destination, start: dstOffsetElements }
+ );
+ }
+ }
+
+ /**
+ * Used for checking whether the whole texture was updated correctly by
+ * `uploadLinearTextureDataToTextureSubpart`. Takes fullData returned by
+ * `copyWholeTextureToNewBuffer` before the copy operation which is the original texture data,
+ * then updates it with `updateLinearTextureDataSubpart` and checks the texture against the
+ * updated data after the copy operation.
+ */
+ copyWholeTextureToBufferAndCheckContentsWithUpdatedData(
+ { texture, mipLevel, origin },
+ fullTextureCopyLayout,
+ texturePartialDataLayout,
+ copySize,
+ format,
+ fullData,
+ partialData
+ ) {
+ const { mipSize, bytesPerRow, rowsPerImage, byteLength } = fullTextureCopyLayout;
+ const readbackPromise = this.readGPUBufferRangeTyped(fullData, {
+ type: Uint8Array,
+ typedLength: byteLength,
+ });
+
+ const destinationOrigin = { x: 0, y: 0, z: 0 };
+
+ // We add an eventual async expectation which will update the full data and then add
+ // other eventual async expectations to ensure it will be correct.
+ this.eventualAsyncExpectation(async () => {
+ const readback = await readbackPromise;
+ this.updateLinearTextureDataSubBox(
+ { offset: 0, ...fullTextureCopyLayout },
+ texturePartialDataLayout,
+ copySize,
+ destinationOrigin,
+ origin,
+ format,
+ readback.data,
+ partialData
+ );
+
+ this.copyPartialTextureToBufferAndCheckContents(
+ { texture, mipLevel, origin: destinationOrigin },
+ { width: mipSize[0], height: mipSize[1], depthOrArrayLayers: mipSize[2] },
+ format,
+ readback.data,
+ { bytesPerRow, rowsPerImage, offset: 0 }
+ );
+
+ readback.cleanup();
+ });
+ }
+
+ /**
+ * Tests copy between linear data and texture by creating a texture, putting some data into it
+ * with WriteTexture/CopyB2T, then getting data for the whole texture/for a part of it back and
+ * comparing it with the expectation.
+ */
+ uploadTextureAndVerifyCopy({
+ textureDataLayout,
+ copySize,
+ dataSize,
+ mipLevel = 0,
+ origin = { x: 0, y: 0, z: 0 },
+ textureSize,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ changeBeforePass = 'none',
+ }) {
+ const texture = this.device.createTexture({
+ size: textureSize,
+ format,
+ dimension,
+ mipLevelCount: mipLevel + 1,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+ this.trackForCleanup(texture);
+
+ const data = dataGenerator.generateView(dataSize);
+
+ switch (checkMethod) {
+ case 'PartialCopyT2B': {
+ this.uploadLinearTextureDataToTextureSubBox(
+ { texture, mipLevel, origin },
+ textureDataLayout,
+ copySize,
+ data,
+ initMethod,
+ changeBeforePass
+ );
+
+ this.copyPartialTextureToBufferAndCheckContents(
+ { texture, mipLevel, origin },
+ copySize,
+ format,
+ data,
+ textureDataLayout,
+ changeBeforePass
+ );
+
+ break;
+ }
+ case 'FullCopyT2B': {
+ const fullTextureCopyLayout = getTextureCopyLayout(format, dimension, textureSize, {
+ mipLevel,
+ });
+
+ const fullData = this.copyWholeTextureToNewBuffer(
+ { texture, mipLevel },
+ fullTextureCopyLayout
+ );
+
+ this.uploadLinearTextureDataToTextureSubBox(
+ { texture, mipLevel, origin },
+ textureDataLayout,
+ copySize,
+ data,
+ initMethod,
+ changeBeforePass
+ );
+
+ this.copyWholeTextureToBufferAndCheckContentsWithUpdatedData(
+ { texture, mipLevel, origin },
+ fullTextureCopyLayout,
+ textureDataLayout,
+ copySize,
+ format,
+ fullData,
+ data
+ );
+
+ break;
+ }
+ default:
+ unreachable();
+ }
+ }
+
+ async DoUploadToStencilTest(
+ format,
+ textureSize,
+ uploadMethod,
+ bytesPerRow,
+ rowsPerImage,
+ initialDataSize,
+ initialDataOffset,
+ mipLevel
+ ) {
+ const srcTexture = this.device.createTexture({
+ size: textureSize,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ format,
+ mipLevelCount: mipLevel + 1,
+ });
+ this.trackForCleanup(srcTexture);
+
+ const copySize = [textureSize[0] >> mipLevel, textureSize[1] >> mipLevel, textureSize[2]];
+ const initialData = dataGenerator.generateView(
+ align(initialDataSize, kBufferSizeAlignment),
+ 0,
+ initialDataOffset
+ );
+
+ switch (uploadMethod) {
+ case 'WriteTexture':
+ this.queue.writeTexture(
+ { texture: srcTexture, aspect: 'stencil-only', mipLevel },
+ initialData,
+ {
+ offset: initialDataOffset,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ copySize
+ );
+
+ break;
+ case 'CopyB2T':
+ {
+ const stagingBuffer = makeBufferWithContents(
+ this.device,
+ initialData,
+ GPUBufferUsage.COPY_SRC
+ );
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyBufferToTexture(
+ { buffer: stagingBuffer, offset: initialDataOffset, bytesPerRow, rowsPerImage },
+ { texture: srcTexture, aspect: 'stencil-only', mipLevel },
+ copySize
+ );
+
+ this.queue.submit([encoder.finish()]);
+ }
+ break;
+ default:
+ unreachable();
+ }
+
+ await this.checkStencilTextureContent(
+ srcTexture,
+ textureSize,
+ format,
+ initialData,
+ initialDataOffset,
+ bytesPerRow,
+ rowsPerImage,
+ mipLevel
+ );
+ }
+
+ async DoCopyFromStencilTest(format, textureSize, bytesPerRow, rowsPerImage, offset, mipLevel) {
+ const srcTexture = this.device.createTexture({
+ size: textureSize,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ format,
+ mipLevelCount: mipLevel + 1,
+ });
+ this.trackForCleanup(srcTexture);
+
+ // Initialize srcTexture with queue.writeTexture()
+ const copySize = [textureSize[0] >> mipLevel, textureSize[1] >> mipLevel, textureSize[2]];
+ const initialData = dataGenerator.generateView(
+ align(copySize[0] * copySize[1] * copySize[2], kBufferSizeAlignment)
+ );
+
+ this.queue.writeTexture(
+ { texture: srcTexture, aspect: 'stencil-only', mipLevel },
+ initialData,
+ { bytesPerRow: copySize[0], rowsPerImage: copySize[1] },
+ copySize
+ );
+
+ // Copy the stencil aspect from srcTexture into outputBuffer.
+ const outputBufferSize = align(
+ offset +
+ dataBytesForCopyOrFail({
+ layout: { bytesPerRow, rowsPerImage },
+ format: 'stencil8',
+ copySize,
+ method: 'CopyT2B',
+ }),
+ kBufferSizeAlignment
+ );
+
+ const outputBuffer = this.device.createBuffer({
+ size: outputBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(outputBuffer);
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToBuffer(
+ { texture: srcTexture, aspect: 'stencil-only', mipLevel },
+ { buffer: outputBuffer, offset, bytesPerRow, rowsPerImage },
+ copySize
+ );
+
+ this.queue.submit([encoder.finish()]);
+
+ // Validate the data in outputBuffer is what we expect.
+ const expectedData = new Uint8Array(outputBufferSize);
+ for (let z = 0; z < copySize[2]; ++z) {
+ const baseExpectedOffset = offset + z * bytesPerRow * rowsPerImage;
+ const baseInitialDataOffset = z * copySize[0] * copySize[1];
+ for (let y = 0; y < copySize[1]; ++y) {
+ memcpy(
+ {
+ src: initialData,
+ start: baseInitialDataOffset + y * copySize[0],
+ length: copySize[0],
+ },
+ { dst: expectedData, start: baseExpectedOffset + y * bytesPerRow }
+ );
+ }
+ }
+ this.expectGPUBufferValuesEqual(outputBuffer, expectedData);
+ }
+
+ // MAINTENANCE_TODO(#881): Migrate this into the texture_ok helpers.
+ async checkStencilTextureContent(
+ stencilTexture,
+ stencilTextureSize,
+ stencilTextureFormat,
+ expectedStencilTextureData,
+ expectedStencilTextureDataOffset,
+ expectedStencilTextureDataBytesPerRow,
+ expectedStencilTextureDataRowsPerImage,
+ stencilTextureMipLevel
+ ) {
+ const stencilBitCount = 8;
+
+ // Prepare the uniform buffer that stores the bit indices (from 0 to 7) at stride 256 (required
+ // by Dynamic Buffer Offset).
+ const uniformBufferSize = kMinDynamicBufferOffsetAlignment * (stencilBitCount - 1) + 4;
+ const uniformBufferData = new Uint32Array(uniformBufferSize / 4);
+ for (let i = 1; i < stencilBitCount; ++i) {
+ uniformBufferData[(kMinDynamicBufferOffsetAlignment / 4) * i] = i;
+ }
+ const uniformBuffer = makeBufferWithContents(
+ this.device,
+ uniformBufferData,
+ GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM
+ );
+
+ // Prepare the base render pipeline descriptor (all the settings expect stencilReadMask).
+ const bindGroupLayout = this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ buffer: {
+ type: 'uniform',
+ minBindingSize: 4,
+ hasDynamicOffset: true,
+ },
+ },
+ ],
+ });
+ const renderPipelineDescriptorBase = {
+ layout: this.device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)-> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Params {
+ stencilBitIndex: u32
+ };
+ @group(0) @binding(0) var<uniform> param: Params;
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(f32(1u << param.stencilBitIndex) / 255.0, 0.0, 0.0, 0.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [
+ {
+ // As we implement "rendering one bit in each draw() call" with blending operation
+ // 'add', the format of outputTexture must support blending.
+ format: 'r8unorm',
+ blend: {
+ color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
+ alpha: {},
+ },
+ },
+ ],
+ },
+
+ primitive: {
+ topology: 'triangle-list',
+ },
+
+ depthStencil: {
+ format: stencilTextureFormat,
+ stencilFront: {
+ compare: 'equal',
+ },
+ stencilBack: {
+ compare: 'equal',
+ },
+ },
+ };
+
+ // Prepare the bindGroup that contains uniformBuffer and referenceTexture.
+ const bindGroup = this.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ size: 4,
+ },
+ },
+ ],
+ });
+
+ // "Copy" the stencil value into the color attachment with 8 draws in one render pass. Each draw
+ // will "Copy" one bit of the stencil value into the color attachment. The bit of the stencil
+ // value is specified by setStencilReference().
+ const copyFromOutputTextureLayout = getTextureCopyLayout(
+ stencilTextureFormat,
+ '2d',
+ [stencilTextureSize[0], stencilTextureSize[1], 1],
+ {
+ mipLevel: stencilTextureMipLevel,
+ aspect: 'stencil-only',
+ }
+ );
+
+ const outputTextureSize = [
+ copyFromOutputTextureLayout.mipSize[0],
+ copyFromOutputTextureLayout.mipSize[1],
+ 1,
+ ];
+
+ const outputTexture = this.device.createTexture({
+ format: 'r8unorm',
+ size: outputTextureSize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ this.trackForCleanup(outputTexture);
+
+ for (
+ let stencilTextureLayer = 0;
+ stencilTextureLayer < stencilTextureSize[2];
+ ++stencilTextureLayer
+ ) {
+ const encoder = this.device.createCommandEncoder();
+ const depthStencilAttachment = {
+ view: stencilTexture.createView({
+ baseMipLevel: stencilTextureMipLevel,
+ mipLevelCount: 1,
+ baseArrayLayer: stencilTextureLayer,
+ arrayLayerCount: 1,
+ }),
+ };
+ if (kTextureFormatInfo[stencilTextureFormat].depth) {
+ depthStencilAttachment.depthClearValue = 0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'store';
+ }
+ if (kTextureFormatInfo[stencilTextureFormat].stencil) {
+ depthStencilAttachment.stencilLoadOp = 'load';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+
+ for (let stencilBitIndex = 0; stencilBitIndex < stencilBitCount; ++stencilBitIndex) {
+ const renderPipelineDescriptor = renderPipelineDescriptorBase;
+ assert(renderPipelineDescriptor.depthStencil !== undefined);
+ renderPipelineDescriptor.depthStencil.stencilReadMask = 1 << stencilBitIndex;
+ const renderPipeline = this.device.createRenderPipeline(renderPipelineDescriptor);
+
+ renderPass.setPipeline(renderPipeline);
+ renderPass.setStencilReference(1 << stencilBitIndex);
+ renderPass.setBindGroup(0, bindGroup, [stencilBitIndex * kMinDynamicBufferOffsetAlignment]);
+ renderPass.draw(6);
+ }
+ renderPass.end();
+
+ // Check outputTexture by copying the content of outputTexture into outputStagingBuffer and
+ // checking all the data in outputStagingBuffer.
+ const outputStagingBuffer = this.device.createBuffer({
+ size: copyFromOutputTextureLayout.byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(outputStagingBuffer);
+ encoder.copyTextureToBuffer(
+ {
+ texture: outputTexture,
+ },
+ {
+ buffer: outputStagingBuffer,
+ bytesPerRow: copyFromOutputTextureLayout.bytesPerRow,
+ rowsPerImage: copyFromOutputTextureLayout.rowsPerImage,
+ },
+ outputTextureSize
+ );
+
+ this.queue.submit([encoder.finish()]);
+
+ // Check the valid data in outputStagingBuffer once per row.
+ for (let y = 0; y < copyFromOutputTextureLayout.mipSize[1]; ++y) {
+ this.expectGPUBufferValuesEqual(
+ outputStagingBuffer,
+ expectedStencilTextureData.slice(
+ expectedStencilTextureDataOffset +
+ expectedStencilTextureDataBytesPerRow *
+ expectedStencilTextureDataRowsPerImage *
+ stencilTextureLayer +
+ expectedStencilTextureDataBytesPerRow * y,
+ copyFromOutputTextureLayout.mipSize[0]
+ )
+ );
+ }
+ }
+ }
+
+ // MAINTENANCE_TODO(#881): Consider if this can be simplified/encapsulated using TexelView.
+ initializeDepthAspectWithRendering(
+ depthTexture,
+ depthFormat,
+ copySize,
+ copyMipLevel,
+ initialData
+ ) {
+ assert(kTextureFormatInfo[depthFormat].depth);
+
+ const inputTexture = this.device.createTexture({
+ size: copySize,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
+ format: 'r32float',
+ });
+ this.trackForCleanup(inputTexture);
+ this.queue.writeTexture(
+ { texture: inputTexture },
+ initialData,
+ {
+ bytesPerRow: copySize[0] * 4,
+ rowsPerImage: copySize[1],
+ },
+ copySize
+ );
+
+ const renderPipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)-> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var inputTexture: texture_2d<f32>;
+ @fragment fn main(@builtin(position) fragcoord : vec4<f32>) ->
+ @builtin(frag_depth) f32 {
+ var depthValue : vec4<f32> = textureLoad(inputTexture, vec2<i32>(fragcoord.xy), 0);
+ return depthValue.x;
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ depthStencil: {
+ format: depthFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'always',
+ },
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ for (let z = 0; z < copySize[2]; ++z) {
+ const depthStencilAttachment = {
+ view: depthTexture.createView({
+ dimension: '2d',
+ baseArrayLayer: z,
+ arrayLayerCount: 1,
+ baseMipLevel: copyMipLevel,
+ mipLevelCount: 1,
+ }),
+ };
+ if (kTextureFormatInfo[depthFormat].depth) {
+ depthStencilAttachment.depthClearValue = 0.0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'store';
+ }
+ if (kTextureFormatInfo[depthFormat].stencil) {
+ depthStencilAttachment.stencilLoadOp = 'load';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment,
+ });
+ renderPass.setPipeline(renderPipeline);
+
+ const bindGroup = this.device.createBindGroup({
+ layout: renderPipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: inputTexture.createView({
+ dimension: '2d',
+ baseArrayLayer: z,
+ arrayLayerCount: 1,
+ baseMipLevel: 0,
+ mipLevelCount: 1,
+ }),
+ },
+ ],
+ });
+ renderPass.setBindGroup(0, bindGroup);
+ renderPass.draw(6);
+ renderPass.end();
+ }
+
+ this.queue.submit([encoder.finish()]);
+ }
+
+ DoCopyTextureToBufferWithDepthAspectTest(
+ format,
+ copySize,
+ bytesPerRowPadding,
+ rowsPerImagePadding,
+ offset,
+ dataPaddingInBytes,
+ mipLevel
+ ) {
+ // [2]: need to convert the float32 values in initialData into the ones compatible
+ // to the depth aspect of depthFormats when depth16unorm is supported by the browsers.
+
+ // Generate the initial depth data uploaded to the texture as float32.
+ const initialData = new Float32Array(copySize[0] * copySize[1] * copySize[2]);
+ for (let i = 0; i < initialData.length; ++i) {
+ const baseValue = 0.05 * i;
+
+ // We expect there are both 1's and 0's in initialData.
+ initialData[i] = i % 40 === 0 ? 1 : baseValue - Math.floor(baseValue);
+ assert(initialData[i] >= 0 && initialData[i] <= 1);
+ }
+
+ // The data uploaded to the texture, using the byte pattern of the format.
+ let formatInitialData = initialData;
+
+ // For unorm depth formats, replace the uploaded depth data with quantized data to avoid
+ // rounding issues when converting from 32float to 16unorm.
+ if (format === 'depth16unorm') {
+ const u16Data = new Uint16Array(initialData.length);
+ for (let i = 0; i < initialData.length; i++) {
+ u16Data[i] = initialData[i] * 65535;
+ initialData[i] = u16Data[i] / 65535.0;
+ }
+ formatInitialData = u16Data;
+ }
+
+ // Initialize the depth aspect of the source texture
+ const depthTexture = this.device.createTexture({
+ format,
+ size: [copySize[0] << mipLevel, copySize[1] << mipLevel, copySize[2]],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ mipLevelCount: mipLevel + 1,
+ });
+ this.trackForCleanup(depthTexture);
+ this.initializeDepthAspectWithRendering(depthTexture, format, copySize, mipLevel, initialData);
+
+ // Copy the depth aspect of the texture into the destination buffer.
+ const aspectBytesPerBlock = depthStencilFormatAspectSize(format, 'depth-only');
+ const bytesPerRow =
+ align(aspectBytesPerBlock * copySize[0], kBytesPerRowAlignment) +
+ bytesPerRowPadding * kBytesPerRowAlignment;
+ const rowsPerImage = copySize[1] + rowsPerImagePadding;
+
+ const destinationBufferSize = align(
+ bytesPerRow * rowsPerImage * copySize[2] +
+ bytesPerRow * (copySize[1] - 1) +
+ aspectBytesPerBlock * copySize[0] +
+ offset +
+ dataPaddingInBytes,
+ kBufferSizeAlignment
+ );
+
+ const destinationBuffer = this.device.createBuffer({
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ size: destinationBufferSize,
+ });
+ this.trackForCleanup(destinationBuffer);
+ const copyEncoder = this.device.createCommandEncoder();
+ copyEncoder.copyTextureToBuffer(
+ {
+ texture: depthTexture,
+ mipLevel,
+ aspect: 'depth-only',
+ },
+ {
+ buffer: destinationBuffer,
+ offset,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ copySize
+ );
+
+ this.queue.submit([copyEncoder.finish()]);
+
+ // Validate the data in destinationBuffer is what we expect.
+ const expectedData = new Uint8Array(destinationBufferSize);
+ for (let z = 0; z < copySize[2]; ++z) {
+ const baseExpectedOffset = z * bytesPerRow * rowsPerImage + offset;
+ const baseInitialDataOffset = z * copySize[0] * copySize[1];
+ for (let y = 0; y < copySize[1]; ++y) {
+ memcpy(
+ {
+ src: formatInitialData,
+ start: baseInitialDataOffset + y * copySize[0],
+ length: copySize[0],
+ },
+ { dst: expectedData, start: baseExpectedOffset + y * bytesPerRow }
+ );
+ }
+ }
+ this.expectGPUBufferValuesEqual(destinationBuffer, expectedData);
+ }
+}
+
+/**
+ * This is a helper function used for filtering test parameters
+ *
+ * [3]: Modify this after introducing tests with rendering.
+ */
+function formatCanBeTested({ format }) {
+ return kTextureFormatInfo[format].copyDst && kTextureFormatInfo[format].copySrc;
+}
+
+export const g = makeTestGroup(ImageCopyTest);
+
+const kRowsPerImageAndBytesPerRowParams = {
+ paddings: [
+ { bytesPerRowPadding: 0, rowsPerImagePadding: 0 }, // no padding
+ { bytesPerRowPadding: 0, rowsPerImagePadding: 6 }, // rowsPerImage padding
+ { bytesPerRowPadding: 6, rowsPerImagePadding: 0 }, // bytesPerRow padding
+ { bytesPerRowPadding: 15, rowsPerImagePadding: 17 }, // both paddings
+ ],
+
+ copySizes: [
+ // In the two cases below, for (WriteTexture, PartialCopyB2T) and (CopyB2T, FullCopyT2B)
+ // sets of methods we will have bytesPerRow = 256 and copyDepth % 2 == { 0, 1 }
+ // respectively. This covers a special code path for D3D12.
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 5 }, // standard copy
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 2 }, // standard copy
+
+ { copyWidthInBlocks: 0, copyHeightInBlocks: 4, copyDepth: 5 }, // empty copy because of width
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 0, copyDepth: 5 }, // empty copy because of height
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 0 }, // empty copy because of depthOrArrayLayers
+ { copyWidthInBlocks: 256, copyHeightInBlocks: 3, copyDepth: 2 }, // copyWidth is 256-aligned
+ { copyWidthInBlocks: 1, copyHeightInBlocks: 3, copyDepth: 5 }, // copyWidth = 1
+
+ // The two cases below cover another special code path for D3D12.
+ // - For (WriteTexture, FullCopyT2B) with r8unorm:
+ // bytesPerRow = 15 = 3 * 5 = bytesInACompleteCopyImage.
+ { copyWidthInBlocks: 32, copyHeightInBlocks: 1, copyDepth: 8 }, // copyHeight = 1
+ // - For (CopyB2T, FullCopyT2B) and (WriteTexture, PartialCopyT2B) with r8unorm:
+ // bytesPerRow = 256 = 8 * 32 = bytesInACompleteCopyImage.
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 1 }, // copyDepth = 1
+
+ { copyWidthInBlocks: 7, copyHeightInBlocks: 1, copyDepth: 1 }, // copyHeight = 1 and copyDepth = 1
+ ],
+
+ // Copy sizes that are suitable for 1D texture and check both some copy sizes and empty copies.
+ copySizes1D: [
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 1, copyDepth: 1 },
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 1, copyDepth: 1 },
+
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 0, copyDepth: 1 },
+ { copyWidthInBlocks: 0, copyHeightInBlocks: 1, copyDepth: 1 },
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 1, copyDepth: 0 },
+ ],
+};
+
+g.test('rowsPerImage_and_bytesPerRow')
+ .desc(
+ `Test that copying data with various bytesPerRow and rowsPerImage values and minimum required
+bytes in copy works for every format.
+
+ Covers a special code path for Metal:
+ bufferSize - offset < bytesPerImage * copyExtent.depthOrArrayLayers
+ Covers a special code path for D3D12:
+ when bytesPerRow is not a multiple of 512 and copyExtent.depthOrArrayLayers > 1: copyExtent.depthOrArrayLayers % 2 == { 0, 1 }
+ bytesPerRow == bytesInACompleteCopyImage
+
+ TODO: Cover the special code paths for 3D textures in D3D12.
+ `
+ )
+ .params(u =>
+ u
+ .combineWithParams(kMethodsToTest)
+ .combine('format', kWorkingColorTextureFormats)
+ .filter(formatCanBeTested)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combineWithParams(kRowsPerImageAndBytesPerRowParams.paddings)
+ .expandWithParams(p => {
+ if (p.dimension === '1d') {
+ return kRowsPerImageAndBytesPerRowParams.copySizes1D;
+ }
+ return kRowsPerImageAndBytesPerRowParams.copySizes;
+ })
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ bytesPerRowPadding,
+ rowsPerImagePadding,
+ copyWidthInBlocks,
+ copyHeightInBlocks,
+ copyDepth,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+ // For CopyB2T and CopyT2B we need to have bytesPerRow 256-aligned,
+ // to make this happen we align the bytesInACompleteRow value and multiply
+ // bytesPerRowPadding by 256.
+ const bytesPerRowAlignment =
+ initMethod === 'WriteTexture' && checkMethod === 'FullCopyT2B' ? 1 : 256;
+
+ const copyWidth = copyWidthInBlocks * info.blockWidth;
+ const copyHeight = copyHeightInBlocks * info.blockHeight;
+ const rowsPerImage = copyHeightInBlocks + rowsPerImagePadding;
+ const bytesPerRow =
+ align(bytesInACompleteRow(copyWidth, format), bytesPerRowAlignment) +
+ bytesPerRowPadding * bytesPerRowAlignment;
+ const copySize = { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth };
+
+ const dataSize = dataBytesForCopyOrFail({
+ layout: { offset: 0, bytesPerRow, rowsPerImage },
+ format,
+ copySize,
+ method: initMethod,
+ });
+
+ t.uploadTextureAndVerifyCopy({
+ textureDataLayout: { offset: 0, bytesPerRow, rowsPerImage },
+ copySize,
+ dataSize,
+ textureSize: [
+ Math.max(copyWidth, info.blockWidth),
+ Math.max(copyHeight, info.blockHeight),
+ Math.max(copyDepth, 1),
+ ],
+ /* making sure the texture is non-empty */ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ });
+ });
+
+const kOffsetsAndSizesParams = {
+ offsetsAndPaddings: [
+ { offsetInBlocks: 0, dataPaddingInBytes: 0 }, // no offset and no padding
+ { offsetInBlocks: 1, dataPaddingInBytes: 0 }, // offset = 1
+ { offsetInBlocks: 2, dataPaddingInBytes: 0 }, // offset = 2
+ { offsetInBlocks: 15, dataPaddingInBytes: 0 }, // offset = 15
+ { offsetInBlocks: 16, dataPaddingInBytes: 0 }, // offset = 16
+ { offsetInBlocks: 242, dataPaddingInBytes: 0 }, // for rgba8unorm format: offset + bytesInCopyExtentPerRow = 242 + 12 = 256 = bytesPerRow
+ { offsetInBlocks: 243, dataPaddingInBytes: 0 }, // for rgba8unorm format: offset + bytesInCopyExtentPerRow = 243 + 12 > 256 = bytesPerRow
+ { offsetInBlocks: 768, dataPaddingInBytes: 0 }, // for copyDepth = 1, blockWidth = 1 and bytesPerBlock = 1: offset = 768 = 3 * 256 = bytesInACompleteCopyImage
+ { offsetInBlocks: 769, dataPaddingInBytes: 0 }, // for copyDepth = 1, blockWidth = 1 and bytesPerBlock = 1: offset = 769 > 768 = bytesInACompleteCopyImage
+ { offsetInBlocks: 0, dataPaddingInBytes: 1 }, // dataPaddingInBytes > 0
+ { offsetInBlocks: 1, dataPaddingInBytes: 8 }, // offset > 0 and dataPaddingInBytes > 0
+ ],
+ copyDepth: [1, 2],
+};
+
+g.test('offsets_and_sizes')
+ .desc(
+ `Test that copying data with various offset values and additional data paddings
+works for every format with 2d and 2d-array textures.
+
+ Covers two special code paths for D3D12:
+ offset + bytesInCopyExtentPerRow { ==, > } bytesPerRow
+ offset > bytesInACompleteCopyImage
+
+ TODO: Cover the special code paths for 3D textures in D3D12.
+ TODO: Make a variant for depth-stencil formats.
+`
+ )
+ .params(u =>
+ u
+ .combineWithParams(kMethodsToTest)
+ .combine('format', kWorkingColorTextureFormats)
+ .filter(formatCanBeTested)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combineWithParams(kOffsetsAndSizesParams.offsetsAndPaddings)
+ .combine('copyDepth', kOffsetsAndSizesParams.copyDepth) // 2d and 2d-array textures
+ .unless(p => p.dimension === '1d' && p.copyDepth !== 1)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ offsetInBlocks,
+ dataPaddingInBytes,
+ copyDepth,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const offset = offsetInBlocks * info.bytesPerBlock;
+ const copySize = {
+ width: 3 * info.blockWidth,
+ height: 3 * info.blockHeight,
+ depthOrArrayLayers: copyDepth,
+ };
+ let textureHeight = 4 * info.blockHeight;
+ let rowsPerImage = 3;
+ const bytesPerRow = 256;
+
+ if (dimension === '1d') {
+ copySize.height = 1;
+ textureHeight = info.blockHeight;
+ rowsPerImage = 1;
+ }
+ const textureSize = [4 * info.blockWidth, textureHeight, copyDepth];
+
+ const minDataSize = dataBytesForCopyOrFail({
+ layout: { offset, bytesPerRow, rowsPerImage },
+ format,
+ copySize,
+ method: initMethod,
+ });
+ const dataSize = minDataSize + dataPaddingInBytes;
+
+ // We're copying a (3 x 3 x copyDepth) (in texel blocks) part of a (4 x 4 x copyDepth)
+ // (in texel blocks) texture with no origin.
+ t.uploadTextureAndVerifyCopy({
+ textureDataLayout: { offset, bytesPerRow, rowsPerImage },
+ copySize,
+ dataSize,
+ textureSize,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ });
+ });
+
+g.test('origins_and_extents')
+ .desc(
+ `Test that copying slices of a texture works with various origin and copyExtent values
+for all formats. We pass origin and copyExtent as [number, number, number].`
+ )
+ .params(u =>
+ u
+ .combineWithParams(kMethodsToTest)
+ .combine('format', kWorkingColorTextureFormats)
+ .filter(formatCanBeTested)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('originValueInBlocks', [0, 7, 8])
+ .combine('copySizeValueInBlocks', [0, 7, 8])
+ .combine('textureSizePaddingValueInBlocks', [0, 7, 8])
+ .unless(
+ p =>
+ // we can't create an empty texture
+ p.copySizeValueInBlocks + p.originValueInBlocks + p.textureSizePaddingValueInBlocks === 0
+ )
+ .combine('coordinateToTest', [0, 1, 2])
+ .unless(p => p.dimension === '1d' && p.coordinateToTest !== 0)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ originValueInBlocks,
+ copySizeValueInBlocks,
+ textureSizePaddingValueInBlocks,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ let originBlocks = [1, 1, 1];
+ let copySizeBlocks = [2, 2, 2];
+ let texSizeBlocks = [3, 3, 3];
+ if (dimension === '1d') {
+ originBlocks = [1, 0, 0];
+ copySizeBlocks = [2, 1, 1];
+ texSizeBlocks = [3, 1, 1];
+ }
+
+ {
+ const ctt = t.params.coordinateToTest;
+ originBlocks[ctt] = originValueInBlocks;
+ copySizeBlocks[ctt] = copySizeValueInBlocks;
+ texSizeBlocks[ctt] =
+ originBlocks[ctt] + copySizeBlocks[ctt] + textureSizePaddingValueInBlocks;
+ }
+
+ const origin = {
+ x: originBlocks[0] * info.blockWidth,
+ y: originBlocks[1] * info.blockHeight,
+ z: originBlocks[2],
+ };
+ const copySize = {
+ width: copySizeBlocks[0] * info.blockWidth,
+ height: copySizeBlocks[1] * info.blockHeight,
+ depthOrArrayLayers: copySizeBlocks[2],
+ };
+ const textureSize = [
+ texSizeBlocks[0] * info.blockWidth,
+ texSizeBlocks[1] * info.blockHeight,
+ texSizeBlocks[2],
+ ];
+
+ const rowsPerImage = copySizeBlocks[1];
+ const bytesPerRow = align(copySizeBlocks[0] * info.bytesPerBlock, 256);
+
+ const dataSize = dataBytesForCopyOrFail({
+ layout: { offset: 0, bytesPerRow, rowsPerImage },
+ format,
+ copySize,
+ method: initMethod,
+ });
+
+ // For testing width: we copy a (_ x 2 x 2) (in texel blocks) part of a (_ x 3 x 3)
+ // (in texel blocks) texture with origin (_, 1, 1) (in texel blocks).
+ // Similarly for other coordinates.
+ t.uploadTextureAndVerifyCopy({
+ textureDataLayout: { offset: 0, bytesPerRow, rowsPerImage },
+ copySize,
+ dataSize,
+ origin,
+ textureSize,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ changeBeforePass: 'arrays',
+ });
+ });
+
+/**
+ * Generates textureSizes which correspond to the same physicalSizeAtMipLevel including virtual
+ * sizes at mip level different from the physical ones.
+ */
+function* generateTestTextureSizes({ format, dimension, mipLevel, _mipSizeInBlocks }) {
+ assert(dimension !== '1d'); // textureSize[1] would be wrong for 1D mipped textures.
+ const info = kTextureFormatInfo[format];
+
+ const widthAtThisLevel = _mipSizeInBlocks.width * info.blockWidth;
+ const heightAtThisLevel = _mipSizeInBlocks.height * info.blockHeight;
+ const textureSize = [
+ widthAtThisLevel << mipLevel,
+ heightAtThisLevel << mipLevel,
+ _mipSizeInBlocks.depthOrArrayLayers << (dimension === '3d' ? mipLevel : 0),
+ ];
+
+ yield textureSize;
+
+ // We choose width and height of the texture so that the values are divisible by blockWidth and
+ // blockHeight respectively and so that the virtual size at mip level corresponds to the same
+ // physical size.
+ // Virtual size at mip level with modified width has width = (physical size width) - (blockWidth / 2).
+ // Virtual size at mip level with modified height has height = (physical size height) - (blockHeight / 2).
+ const widthAtPrevLevel = widthAtThisLevel << 1;
+ const heightAtPrevLevel = heightAtThisLevel << 1;
+ assert(mipLevel > 0);
+ assert(widthAtPrevLevel >= info.blockWidth && heightAtPrevLevel >= info.blockHeight);
+ const modifiedWidth = (widthAtPrevLevel - info.blockWidth) << (mipLevel - 1);
+ const modifiedHeight = (heightAtPrevLevel - info.blockHeight) << (mipLevel - 1);
+
+ const modifyWidth = info.blockWidth > 1 && modifiedWidth !== textureSize[0];
+ const modifyHeight = info.blockHeight > 1 && modifiedHeight !== textureSize[1];
+
+ if (modifyWidth) {
+ yield [modifiedWidth, textureSize[1], textureSize[2]];
+ }
+ if (modifyHeight) {
+ yield [textureSize[0], modifiedHeight, textureSize[2]];
+ }
+ if (modifyWidth && modifyHeight) {
+ yield [modifiedWidth, modifiedHeight, textureSize[2]];
+ }
+
+ if (dimension === '3d') {
+ yield [textureSize[0], textureSize[1], textureSize[2] + 1];
+ }
+}
+
+g.test('mip_levels')
+ .desc(
+ `Test that copying various mip levels works. Covers two special code paths:
+ - The physical size of the subresource is not equal to the logical size.
+ - bufferSize - offset < bytesPerImage * copyExtent.depthOrArrayLayers, and copyExtent needs to be clamped for all block formats.
+ - For 3D textures test copying to a sub-range of the depth.
+
+Tests both 2D and 3D textures. 1D textures are skipped because they can only have one mip level.
+
+TODO: Make a variant for depth-stencil formats.
+ `
+ )
+ .params(u =>
+ u
+ .combineWithParams(kMethodsToTest)
+ .combine('format', kWorkingColorTextureFormats)
+ .filter(formatCanBeTested)
+ .combine('dimension', ['2d', '3d'])
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combineWithParams([
+ // origin + copySize = texturePhysicalSizeAtMipLevel for all coordinates, 2d texture */
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 1 },
+ originInBlocks: { x: 3, y: 2, z: 0 },
+ _mipSizeInBlocks: { width: 8, height: 6, depthOrArrayLayers: 1 },
+ mipLevel: 1,
+ },
+ // origin + copySize = texturePhysicalSizeAtMipLevel for all coordinates, 2d-array texture
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 2 },
+ originInBlocks: { x: 3, y: 2, z: 1 },
+ _mipSizeInBlocks: { width: 8, height: 6, depthOrArrayLayers: 3 },
+ mipLevel: 2,
+ },
+ // origin.x + copySize.width = texturePhysicalSizeAtMipLevel.width
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 2 },
+ originInBlocks: { x: 3, y: 2, z: 1 },
+ _mipSizeInBlocks: { width: 8, height: 7, depthOrArrayLayers: 4 },
+ mipLevel: 3,
+ },
+ // origin.y + copySize.height = texturePhysicalSizeAtMipLevel.height
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 2 },
+ originInBlocks: { x: 3, y: 2, z: 1 },
+ _mipSizeInBlocks: { width: 9, height: 6, depthOrArrayLayers: 4 },
+ mipLevel: 4,
+ },
+ // origin.z + copySize.depthOrArrayLayers = texturePhysicalSizeAtMipLevel.depthOrArrayLayers
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 2 },
+ originInBlocks: { x: 3, y: 2, z: 1 },
+ _mipSizeInBlocks: { width: 9, height: 7, depthOrArrayLayers: 3 },
+ mipLevel: 4,
+ },
+ // origin + copySize < texturePhysicalSizeAtMipLevel for all coordinates
+ {
+ copySizeInBlocks: { width: 5, height: 4, depthOrArrayLayers: 2 },
+ originInBlocks: { x: 3, y: 2, z: 1 },
+ _mipSizeInBlocks: { width: 9, height: 7, depthOrArrayLayers: 4 },
+ mipLevel: 4,
+ },
+ ])
+ .expand('textureSize', generateTestTextureSizes)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ copySizeInBlocks,
+ originInBlocks,
+ textureSize,
+ mipLevel,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const origin = {
+ x: originInBlocks.x * info.blockWidth,
+ y: originInBlocks.y * info.blockHeight,
+ z: originInBlocks.z,
+ };
+ const copySize = {
+ width: copySizeInBlocks.width * info.blockWidth,
+ height: copySizeInBlocks.height * info.blockHeight,
+ depthOrArrayLayers: copySizeInBlocks.depthOrArrayLayers,
+ };
+
+ const rowsPerImage = copySizeInBlocks.height + 1;
+ const bytesPerRow = align(copySize.width, 256);
+
+ const dataSize = dataBytesForCopyOrFail({
+ layout: { offset: 0, bytesPerRow, rowsPerImage },
+ format,
+ copySize,
+ method: initMethod,
+ });
+
+ t.uploadTextureAndVerifyCopy({
+ textureDataLayout: { offset: 0, bytesPerRow, rowsPerImage },
+ copySize,
+ dataSize,
+ origin,
+ mipLevel,
+ textureSize,
+ format,
+ dimension,
+ initMethod,
+ checkMethod,
+ });
+ });
+
+const UND = undefined;
+g.test('undefined_params')
+ .desc(
+ `Tests undefined values of bytesPerRow, rowsPerImage, and origin.x/y/z.
+ Ensures bytesPerRow/rowsPerImage=undefined are valid and behave as expected.
+ Ensures origin.x/y/z undefined default to 0.`
+ )
+ .params(u =>
+ u
+ .combineWithParams(kMethodsToTest)
+ .combine('dimension', kTextureDimensions)
+ .beginSubcases()
+ .combineWithParams([
+ // copying one row: bytesPerRow and rowsPerImage can be undefined
+ { copySize: [3, 1, 1], origin: [UND, UND, UND], bytesPerRow: UND, rowsPerImage: UND },
+ // copying one slice: rowsPerImage can be undefined
+ { copySize: [3, 1, 1], origin: [UND, UND, UND], bytesPerRow: 256, rowsPerImage: UND },
+ { copySize: [3, 3, 1], origin: [UND, UND, UND], bytesPerRow: 256, rowsPerImage: UND },
+ // copying two slices
+ { copySize: [3, 3, 2], origin: [UND, UND, UND], bytesPerRow: 256, rowsPerImage: 3 },
+ // origin.x = undefined
+ { copySize: [1, 1, 1], origin: [UND, 1, 1], bytesPerRow: UND, rowsPerImage: UND },
+ // origin.y = undefined
+ { copySize: [1, 1, 1], origin: [1, UND, 1], bytesPerRow: UND, rowsPerImage: UND },
+ // origin.z = undefined
+ { copySize: [1, 1, 1], origin: [1, 1, UND], bytesPerRow: UND, rowsPerImage: UND },
+ ])
+ .expandWithParams(p => [
+ {
+ _textureSize: [
+ 100,
+ p.copySize[1] + (p.origin[1] ?? 0),
+ p.copySize[2] + (p.origin[2] ?? 0),
+ ],
+ },
+ ])
+ .unless(p => p.dimension === '1d' && (p._textureSize[1] > 1 || p._textureSize[2] > 1))
+ )
+ .fn(async t => {
+ const {
+ dimension,
+ _textureSize,
+ bytesPerRow,
+ rowsPerImage,
+ copySize,
+ origin,
+ initMethod,
+ checkMethod,
+ } = t.params;
+
+ t.uploadTextureAndVerifyCopy({
+ textureDataLayout: {
+ offset: 0,
+ // Zero will get turned back into undefined later.
+ bytesPerRow: bytesPerRow ?? 0,
+ // Zero will get turned back into undefined later.
+ rowsPerImage: rowsPerImage ?? 0,
+ },
+ copySize: { width: copySize[0], height: copySize[1], depthOrArrayLayers: copySize[2] },
+ dataSize: 2000,
+ textureSize: _textureSize,
+ // Zeros will get turned back into undefined later.
+ origin: { x: origin[0] ?? 0, y: origin[1] ?? 0, z: origin[2] ?? 0 },
+ format: 'rgba8unorm',
+ dimension,
+ initMethod,
+ checkMethod,
+ changeBeforePass: 'undefined',
+ });
+ });
+
+function CopyMethodSupportedWithDepthStencilFormat(aspect, format, copyMethod) {
+ {
+ return (
+ (aspect === 'stencil-only' && kTextureFormatInfo[format].stencil) ||
+ (aspect === 'depth-only' &&
+ kTextureFormatInfo[format].depth &&
+ copyMethod === 'CopyT2B' &&
+ depthStencilBufferTextureCopySupported('CopyT2B', format, aspect))
+ );
+ }
+}
+
+g.test('rowsPerImage_and_bytesPerRow_depth_stencil')
+ .desc(
+ `Test that copying data with various bytesPerRow and rowsPerImage values and minimum required
+bytes in copy works for copyBufferToTexture(), copyTextureToBuffer() and writeTexture() with stencil
+aspect and copyTextureToBuffer() with depth aspect.
+
+ Covers a special code path for Metal:
+ bufferSize - offset < bytesPerImage * copyExtent.depthOrArrayLayers
+ Covers a special code path for D3D12:
+ when bytesPerRow is not a multiple of 512 and copyExtent.depthOrArrayLayers > 1:
+ copyExtent.depthOrArrayLayers % 2 == { 0, 1 }
+ bytesPerRow == bytesInACompleteCopyImage
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .combine('copyMethod', ['WriteTexture', 'CopyB2T', 'CopyT2B'])
+ .combine('aspect', ['depth-only', 'stencil-only'])
+ .filter(t => CopyMethodSupportedWithDepthStencilFormat(t.aspect, t.format, t.copyMethod))
+ .beginSubcases()
+ .combineWithParams(kRowsPerImageAndBytesPerRowParams.paddings)
+ .combineWithParams(kRowsPerImageAndBytesPerRowParams.copySizes)
+ .filter(t => {
+ return t.copyWidthInBlocks * t.copyHeightInBlocks * t.copyDepth > 0;
+ })
+ .combine('mipLevel', [0, 2])
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ format,
+ copyMethod,
+ aspect,
+ bytesPerRowPadding,
+ rowsPerImagePadding,
+ copyWidthInBlocks,
+ copyHeightInBlocks,
+ copyDepth,
+ mipLevel,
+ } = t.params;
+ const bytesPerBlock = depthStencilFormatAspectSize(format, aspect);
+ const rowsPerImage = copyHeightInBlocks + rowsPerImagePadding;
+
+ const bytesPerRowAlignment = copyMethod === 'WriteTexture' ? 1 : kBytesPerRowAlignment;
+ const bytesPerRow =
+ align(bytesPerBlock * copyWidthInBlocks, bytesPerRowAlignment) +
+ bytesPerRowPadding * bytesPerRowAlignment;
+
+ const copySize = [copyWidthInBlocks, copyHeightInBlocks, copyDepth];
+ const textureSize = [copyWidthInBlocks << mipLevel, copyHeightInBlocks << mipLevel, copyDepth];
+
+ if (copyMethod === 'CopyT2B') {
+ if (aspect === 'depth-only') {
+ t.DoCopyTextureToBufferWithDepthAspectTest(
+ format,
+ copySize,
+ bytesPerRowPadding,
+ rowsPerImagePadding,
+ 0,
+ 0,
+ mipLevel
+ );
+ } else {
+ await t.DoCopyFromStencilTest(format, textureSize, bytesPerRow, rowsPerImage, 0, mipLevel);
+ }
+ } else {
+ assert(
+ aspect === 'stencil-only' && (copyMethod === 'CopyB2T' || copyMethod === 'WriteTexture')
+ );
+
+ const initialDataSize = dataBytesForCopyOrFail({
+ layout: { bytesPerRow, rowsPerImage },
+ format: 'stencil8',
+ copySize,
+ method: copyMethod,
+ });
+
+ await t.DoUploadToStencilTest(
+ format,
+ textureSize,
+ copyMethod,
+ bytesPerRow,
+ rowsPerImage,
+ initialDataSize,
+ 0,
+ mipLevel
+ );
+ }
+ });
+
+g.test('offsets_and_sizes_copy_depth_stencil')
+ .desc(
+ `Test that copying data with various offset values and additional data paddings
+works for copyBufferToTexture(), copyTextureToBuffer() and writeTexture() with stencil aspect and
+copyTextureToBuffer() with depth aspect.
+
+ Covers two special code paths for D3D12:
+ offset + bytesInCopyExtentPerRow { ==, > } bytesPerRow
+ offset > bytesInACompleteCopyImage
+`
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .combine('copyMethod', ['WriteTexture', 'CopyB2T', 'CopyT2B'])
+ .combine('aspect', ['depth-only', 'stencil-only'])
+ .filter(t => CopyMethodSupportedWithDepthStencilFormat(t.aspect, t.format, t.copyMethod))
+ .beginSubcases()
+ .combineWithParams(kOffsetsAndSizesParams.offsetsAndPaddings)
+ .filter(t => t.offsetInBlocks % 4 === 0)
+ .combine('copyDepth', kOffsetsAndSizesParams.copyDepth)
+ .combine('mipLevel', [0, 2])
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ format,
+ copyMethod,
+ aspect,
+ offsetInBlocks,
+ dataPaddingInBytes,
+ copyDepth,
+ mipLevel,
+ } = t.params;
+ const bytesPerBlock = depthStencilFormatAspectSize(format, aspect);
+ const initialDataOffset = offsetInBlocks * bytesPerBlock;
+ const copySize = [3, 3, copyDepth];
+ const rowsPerImage = 3;
+ const bytesPerRow = 256;
+
+ const textureSize = [copySize[0] << mipLevel, copySize[1] << mipLevel, copyDepth];
+ if (copyMethod === 'CopyT2B') {
+ if (aspect === 'depth-only') {
+ t.DoCopyTextureToBufferWithDepthAspectTest(format, copySize, 0, 0, 0, 0, mipLevel);
+ } else {
+ await t.DoCopyFromStencilTest(
+ format,
+ textureSize,
+ bytesPerRow,
+ rowsPerImage,
+ initialDataOffset,
+ mipLevel
+ );
+ }
+ } else {
+ assert(
+ aspect === 'stencil-only' && (copyMethod === 'CopyB2T' || copyMethod === 'WriteTexture')
+ );
+
+ const minDataSize = dataBytesForCopyOrFail({
+ layout: { offset: initialDataOffset, bytesPerRow, rowsPerImage },
+ format: 'stencil8',
+ copySize,
+ method: copyMethod,
+ });
+ const initialDataSize = minDataSize + dataPaddingInBytes;
+ await t.DoUploadToStencilTest(
+ format,
+ textureSize,
+ copyMethod,
+ bytesPerRow,
+ rowsPerImage,
+ initialDataSize,
+ initialDataOffset,
+ mipLevel
+ );
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/programmable_state_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/programmable_state_test.js
new file mode 100644
index 0000000000..e263adf8ea
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/programmable_state_test.js
@@ -0,0 +1,144 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { unreachable } from '../../../../../common/util/util.js';
+import { GPUTest } from '../../../../gpu_test.js';
+
+export class ProgrammableStateTest extends GPUTest {
+ commonBindGroupLayouts = new Map();
+
+ getBindGroupLayout(type) {
+ if (!this.commonBindGroupLayouts.has(type)) {
+ this.commonBindGroupLayouts.set(
+ type,
+ this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
+ buffer: { type },
+ },
+ ],
+ })
+ );
+ }
+ return this.commonBindGroupLayouts.get(type);
+ }
+
+ getBindGroupLayouts(indices) {
+ const bindGroupLayouts = [];
+ bindGroupLayouts[indices.a] = this.getBindGroupLayout('read-only-storage');
+ bindGroupLayouts[indices.b] = this.getBindGroupLayout('read-only-storage');
+ bindGroupLayouts[indices.out] = this.getBindGroupLayout('storage');
+ return bindGroupLayouts;
+ }
+
+ createBindGroup(buffer, type) {
+ return this.device.createBindGroup({
+ layout: this.getBindGroupLayout(type),
+ entries: [{ binding: 0, resource: { buffer } }],
+ });
+ }
+
+ setBindGroup(encoder, index, factory) {
+ encoder.setBindGroup(index, factory(index));
+ }
+
+ // Create a compute pipeline that performs an operation on data from two bind groups,
+ // then writes the result to a third bind group.
+ createBindingStatePipeline(encoderType, groups, algorithm = 'a.value - b.value') {
+ switch (encoderType) {
+ case 'compute pass': {
+ const wgsl = `struct Data {
+ value : i32
+ };
+
+ @group(${groups.a}) @binding(0) var<storage> a : Data;
+ @group(${groups.b}) @binding(0) var<storage> b : Data;
+ @group(${groups.out}) @binding(0) var<storage, read_write> out : Data;
+
+ @compute @workgroup_size(1) fn main() {
+ out.value = ${algorithm};
+ return;
+ }
+ `;
+
+ return this.device.createComputePipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: this.getBindGroupLayouts(groups),
+ }),
+ compute: {
+ module: this.device.createShaderModule({
+ code: wgsl,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ }
+ case 'render pass':
+ case 'render bundle': {
+ const wgslShaders = {
+ vertex: `
+ @vertex fn vert_main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.5, 0.5, 0.0, 1.0);
+ }
+ `,
+
+ fragment: `
+ struct Data {
+ value : i32
+ };
+
+ @group(${groups.a}) @binding(0) var<storage> a : Data;
+ @group(${groups.b}) @binding(0) var<storage> b : Data;
+ @group(${groups.out}) @binding(0) var<storage, read_write> out : Data;
+
+ @fragment fn frag_main() -> @location(0) vec4<f32> {
+ out.value = ${algorithm};
+ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ `,
+ };
+
+ return this.device.createRenderPipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: this.getBindGroupLayouts(groups),
+ }),
+ vertex: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.vertex,
+ }),
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.fragment,
+ }),
+ entryPoint: 'frag_main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ }
+ default:
+ unreachable();
+ }
+ }
+
+ setPipeline(pass, pipeline) {
+ if (pass instanceof GPUComputePassEncoder) {
+ pass.setPipeline(pipeline);
+ } else if (pass instanceof GPURenderPassEncoder || pass instanceof GPURenderBundleEncoder) {
+ pass.setPipeline(pipeline);
+ }
+ }
+
+ dispatchOrDraw(pass) {
+ if (pass instanceof GPUComputePassEncoder) {
+ pass.dispatchWorkgroups(1);
+ } else if (pass instanceof GPURenderPassEncoder) {
+ pass.draw(1);
+ } else if (pass instanceof GPURenderBundleEncoder) {
+ pass.draw(1);
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/state_tracking.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/state_tracking.spec.js
new file mode 100644
index 0000000000..fbd2a102b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/programmable/state_tracking.spec.js
@@ -0,0 +1,319 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Ensure state is set correctly. Tries to stress state caching (setting different states multiple
+times in different orders) for setBindGroup and setPipeline.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../../constants.js';
+import { kProgrammableEncoderTypes } from '../../../../util/command_buffer_maker.js';
+
+import { ProgrammableStateTest } from './programmable_state_test.js';
+
+export const g = makeTestGroup(ProgrammableStateTest);
+
+const kBufferUsage = GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.STORAGE;
+
+g.test('bind_group_indices')
+ .desc(
+ `
+ Test that bind group indices can be declared in any order, regardless of their order in the shader.
+ - Test places the value of buffer a - buffer b into the out buffer, then reads the result.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .beginSubcases()
+ .combine('groupIndices', [
+ { a: 0, b: 1, out: 2 },
+ { a: 1, b: 2, out: 0 },
+ { a: 2, b: 0, out: 1 },
+ { a: 0, b: 2, out: 1 },
+ { a: 2, b: 1, out: 0 },
+ { a: 1, b: 0, out: 2 },
+ ])
+ )
+ .fn(async t => {
+ const { encoderType, groupIndices } = t.params;
+
+ const pipeline = t.createBindingStatePipeline(encoderType, groupIndices);
+
+ const out = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const bindGroups = {
+ a: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ b: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([2]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ out: t.createBindGroup(out, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+
+ t.setPipeline(encoder, pipeline);
+ encoder.setBindGroup(groupIndices.a, bindGroups.a);
+ encoder.setBindGroup(groupIndices.b, bindGroups.b);
+ encoder.setBindGroup(groupIndices.out, bindGroups.out);
+ t.dispatchOrDraw(encoder);
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(out, new Int32Array([1]));
+ });
+
+g.test('bind_group_order')
+ .desc(
+ `
+ Test that the order in which you set the bind groups doesn't matter.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .beginSubcases()
+ .combine('setOrder', [
+ ['a', 'b', 'out'],
+ ['b', 'out', 'a'],
+ ['out', 'a', 'b'],
+ ['b', 'a', 'out'],
+ ['a', 'out', 'b'],
+ ['out', 'b', 'a'],
+ ])
+ )
+ .fn(async t => {
+ const { encoderType, setOrder } = t.params;
+
+ const groupIndices = { a: 0, b: 1, out: 2 };
+ const pipeline = t.createBindingStatePipeline(encoderType, groupIndices);
+
+ const out = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const bindGroups = {
+ a: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ b: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([2]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ out: t.createBindGroup(out, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+ t.setPipeline(encoder, pipeline);
+
+ for (const bindingName of setOrder) {
+ encoder.setBindGroup(groupIndices[bindingName], bindGroups[bindingName]);
+ }
+
+ t.dispatchOrDraw(encoder);
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(out, new Int32Array([1]));
+ });
+
+g.test('bind_group_before_pipeline')
+ .desc(
+ `
+ Test that setting bind groups prior to setting the pipeline is still valid.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .beginSubcases()
+ .combineWithParams([
+ { setBefore: ['a', 'b'], setAfter: ['out'] },
+ { setBefore: ['a'], setAfter: ['b', 'out'] },
+ { setBefore: ['out', 'b'], setAfter: ['a'] },
+ { setBefore: ['a', 'b', 'out'], setAfter: [] },
+ ])
+ )
+ .fn(async t => {
+ const { encoderType, setBefore, setAfter } = t.params;
+ const groupIndices = { a: 0, b: 1, out: 2 };
+ const pipeline = t.createBindingStatePipeline(encoderType, groupIndices);
+
+ const out = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const bindGroups = {
+ a: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ b: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([2]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ out: t.createBindGroup(out, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+
+ for (const bindingName of setBefore) {
+ encoder.setBindGroup(groupIndices[bindingName], bindGroups[bindingName]);
+ }
+
+ t.setPipeline(encoder, pipeline);
+
+ for (const bindingName of setAfter) {
+ encoder.setBindGroup(groupIndices[bindingName], bindGroups[bindingName]);
+ }
+
+ t.dispatchOrDraw(encoder);
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(out, new Int32Array([1]));
+ });
+
+g.test('one_bind_group_multiple_slots')
+ .desc(
+ `
+ Test that a single bind group may be bound to more than one slot.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ )
+ .fn(async t => {
+ const { encoderType } = t.params;
+ const pipeline = t.createBindingStatePipeline(encoderType, { a: 0, b: 1, out: 2 });
+
+ const out = t.makeBufferWithContents(new Int32Array([1]), kBufferUsage);
+ const bindGroups = {
+ ab: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ out: t.createBindGroup(out, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+ t.setPipeline(encoder, pipeline);
+
+ encoder.setBindGroup(0, bindGroups.ab);
+ encoder.setBindGroup(1, bindGroups.ab);
+ encoder.setBindGroup(2, bindGroups.out);
+
+ t.dispatchOrDraw(encoder);
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(out, new Int32Array([0]));
+ });
+
+g.test('bind_group_multiple_sets')
+ .desc(
+ `
+ Test that the last bind group set to a given slot is used when dispatching.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ )
+ .fn(async t => {
+ const { encoderType } = t.params;
+ const pipeline = t.createBindingStatePipeline(encoderType, { a: 0, b: 1, out: 2 });
+
+ const badOut = t.makeBufferWithContents(new Int32Array([-1]), kBufferUsage);
+ const out = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const bindGroups = {
+ a: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ b: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([2]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ c: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([5]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ badOut: t.createBindGroup(badOut, 'storage'),
+ out: t.createBindGroup(out, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+
+ encoder.setBindGroup(1, bindGroups.c);
+
+ t.setPipeline(encoder, pipeline);
+
+ encoder.setBindGroup(0, bindGroups.c);
+ encoder.setBindGroup(0, bindGroups.a);
+
+ encoder.setBindGroup(2, bindGroups.badOut);
+
+ encoder.setBindGroup(1, bindGroups.b);
+ encoder.setBindGroup(2, bindGroups.out);
+
+ t.dispatchOrDraw(encoder);
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(out, new Int32Array([1]));
+ t.expectGPUBufferValuesEqual(badOut, new Int32Array([-1]));
+ });
+
+g.test('compatible_pipelines')
+ .desc('Test that bind groups can be shared between compatible pipelines.')
+ .params(u =>
+ u //
+ .combine('encoderType', kProgrammableEncoderTypes)
+ )
+ .fn(async t => {
+ const { encoderType } = t.params;
+ const pipelineA = t.createBindingStatePipeline(encoderType, { a: 0, b: 1, out: 2 });
+ const pipelineB = t.createBindingStatePipeline(
+ encoderType,
+ { a: 0, b: 1, out: 2 },
+ 'a.value + b.value'
+ );
+
+ const outA = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const outB = t.makeBufferWithContents(new Int32Array([0]), kBufferUsage);
+ const bindGroups = {
+ a: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([3]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ b: t.createBindGroup(
+ t.makeBufferWithContents(new Int32Array([2]), kBufferUsage),
+ 'read-only-storage'
+ ),
+
+ outA: t.createBindGroup(outA, 'storage'),
+ outB: t.createBindGroup(outB, 'storage'),
+ };
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+ encoder.setBindGroup(0, bindGroups.a);
+ encoder.setBindGroup(1, bindGroups.b);
+
+ t.setPipeline(encoder, pipelineA);
+ encoder.setBindGroup(2, bindGroups.outA);
+ t.dispatchOrDraw(encoder);
+
+ t.setPipeline(encoder, pipelineB);
+ encoder.setBindGroup(2, bindGroups.outB);
+ t.dispatchOrDraw(encoder);
+
+ validateFinishAndSubmit(true, true);
+
+ t.expectGPUBufferValuesEqual(outA, new Int32Array([1]));
+ t.expectGPUBufferValuesEqual(outB, new Int32Array([5]));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/dynamic_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/dynamic_state.spec.js
new file mode 100644
index 0000000000..69c91e371d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/dynamic_state.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests of the behavior of the viewport/scissor/blend/reference states.
+
+TODO:
+- {viewport, scissor rect, blend color, stencil reference}:
+ Test rendering result with {various values}.
+ - Set the state in different ways to make sure it gets the correct value in the end: {
+ - state unset (= default)
+ - state explicitly set once to {default value, another value}
+ - persistence: [set, draw, draw] (fn should differentiate from [set, draw] + [draw])
+ - overwriting: [set(1), draw, set(2), draw] (fn should differentiate from [set(1), set(2), draw, draw])
+ - overwriting: [set(1), set(2), draw] (fn should differentiate from [set(1), draw] but not [set(2), draw])
+ - }
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/state_tracking.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/state_tracking.spec.js
new file mode 100644
index 0000000000..dd7725afcd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/command_buffer/render/state_tracking.spec.js
@@ -0,0 +1,636 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Ensure state is set correctly. Tries to stress state caching (setting different states multiple
+times in different orders) for setIndexBuffer and setVertexBuffer.
+Equivalent tests for setBindGroup and setPipeline are in programmable/state_tracking.spec.ts.
+Equivalent tests for viewport/scissor/blend/reference are in render/dynamic_state.spec.ts
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+
+class VertexAndIndexStateTrackingTest extends GPUTest {
+ GetRenderPipelineForTest(arrayStride) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Inputs {
+ @location(0) vertexPosition : f32,
+ @location(1) vertexColor : vec4<f32>,
+ };
+ struct Outputs {
+ @builtin(position) position : vec4<f32>,
+ @location(0) color : vec4<f32>,
+ };
+ @vertex
+ fn main(input : Inputs)-> Outputs {
+ var outputs : Outputs;
+ outputs.position =
+ vec4<f32>(input.vertexPosition, 0.5, 0.0, 1.0);
+ outputs.color = input.vertexColor;
+ return outputs;
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ arrayStride,
+ attributes: [
+ {
+ format: 'float32',
+ offset: 0,
+ shaderLocation: 0,
+ },
+ {
+ format: 'unorm8x4',
+ offset: 4,
+ shaderLocation: 1,
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Input {
+ @location(0) color : vec4<f32>
+ };
+ @fragment
+ fn main(input : Input) -> @location(0) vec4<f32> {
+ return input.color;
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+ }
+
+ kVertexAttributeSize = 8;
+}
+
+export const g = makeTestGroup(VertexAndIndexStateTrackingTest);
+
+g.test('set_index_buffer_without_changing_buffer')
+ .desc(
+ `
+ Test that setting index buffer states (index format, offset, size) multiple times in different
+ orders still keeps the correctness of each draw call.
+`
+ )
+ .fn(async t => {
+ // Initialize the index buffer with 5 uint16 indices (0, 1, 2, 3, 4).
+ const indexBuffer = t.makeBufferWithContents(
+ new Uint16Array([0, 1, 2, 3, 4]),
+ GPUBufferUsage.INDEX
+ );
+
+ // Initialize the vertex buffer with required vertex attributes (position: f32, color: f32x4)
+ // Note that the maximum index in the test is 0x10000.
+ const kVertexAttributesCount = 0x10000 + 1;
+ const vertexBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.VERTEX,
+ size: t.kVertexAttributeSize * kVertexAttributesCount,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(vertexBuffer);
+ const vertexAttributes = vertexBuffer.getMappedRange();
+ const kPositions = [-0.8, -0.4, 0.0, 0.4, 0.8, -0.4];
+ const kColors = [
+ new Uint8Array([255, 0, 0, 255]),
+ new Uint8Array([255, 255, 255, 255]),
+ new Uint8Array([0, 0, 255, 255]),
+ new Uint8Array([255, 0, 255, 255]),
+ new Uint8Array([0, 255, 255, 255]),
+ new Uint8Array([0, 255, 0, 255]),
+ ];
+
+ // Set vertex attributes at index {0..4} in Uint16.
+ // Note that the vertex attribute at index 1 will not be used.
+ for (let i = 0; i < kPositions.length - 1; ++i) {
+ const baseOffset = t.kVertexAttributeSize * i;
+ const vertexPosition = new Float32Array(vertexAttributes, baseOffset, 1);
+ vertexPosition[0] = kPositions[i];
+ const vertexColor = new Uint8Array(vertexAttributes, baseOffset + 4, 4);
+ vertexColor.set(kColors[i]);
+ }
+ // Set vertex attributes at index 0x10000.
+ const lastOffset = t.kVertexAttributeSize * (kVertexAttributesCount - 1);
+ const lastVertexPosition = new Float32Array(vertexAttributes, lastOffset, 1);
+ lastVertexPosition[0] = kPositions[kPositions.length - 1];
+ const lastVertexColor = new Uint8Array(vertexAttributes, lastOffset + 4, 4);
+ lastVertexColor.set(kColors[kColors.length - 1]);
+
+ vertexBuffer.unmap();
+
+ const renderPipeline = t.GetRenderPipelineForTest(t.kVertexAttributeSize);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kPositions.length - 1, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(renderPipeline);
+ renderPass.setVertexBuffer(0, vertexBuffer);
+
+ // 1st draw: indexFormat = 'uint32', offset = 0, size = 4 (index value: 0x10000)
+ renderPass.setIndexBuffer(indexBuffer, 'uint32', 0, 4);
+ renderPass.drawIndexed(1);
+
+ // 2nd draw: indexFormat = 'uint16', offset = 0, size = 4 (index value: 0)
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', 0, 4);
+ renderPass.drawIndexed(1);
+
+ // 3rd draw: indexFormat = 'uint16', offset = 4, size = 2 (index value: 2)
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', 0, 2);
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', 4, 2);
+ renderPass.drawIndexed(1);
+
+ // 4th draw: indexformat = 'uint16', offset = 6, size = 4 (index values: 3, 4)
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', 6, 2);
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', 6, 4);
+ renderPass.drawIndexed(2);
+
+ renderPass.end();
+ t.queue.submit([encoder.finish()]);
+
+ for (let i = 0; i < kPositions.length - 1; ++i) {
+ const expectedColor = i === 1 ? kColors[kPositions.length - 1] : kColors[i];
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ 'rgba8unorm',
+ { x: i, y: 0 },
+ { exp: expectedColor }
+ );
+ }
+ });
+
+g.test('set_vertex_buffer_without_changing_buffer')
+ .desc(
+ `
+ Test that setting vertex buffer states (offset, size) multiple times in different orders still
+ keeps the correctness of each draw call.
+ - Tries several different sequences of setVertexBuffer+draw commands, each of which draws vertices
+ in all 4 output pixels, and check they were drawn correctly.
+`
+ )
+ .fn(async t => {
+ const kPositions = [-0.875, -0.625, -0.375, -0.125, 0.125, 0.375, 0.625, 0.875];
+ const kColors = [
+ new Uint8Array([255, 0, 0, 255]),
+ new Uint8Array([0, 255, 0, 255]),
+ new Uint8Array([0, 0, 255, 255]),
+ new Uint8Array([51, 0, 0, 255]),
+ new Uint8Array([0, 51, 0, 255]),
+ new Uint8Array([0, 0, 51, 255]),
+ new Uint8Array([255, 0, 255, 255]),
+ new Uint8Array([255, 255, 0, 255]),
+ ];
+
+ // Initialize the vertex buffer with required vertex attributes (position: f32, color: f32x4)
+ const kVertexAttributesCount = 8;
+ const vertexBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.VERTEX,
+ size: t.kVertexAttributeSize * kVertexAttributesCount,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(vertexBuffer);
+ const vertexAttributes = vertexBuffer.getMappedRange();
+ for (let i = 0; i < kPositions.length; ++i) {
+ const baseOffset = t.kVertexAttributeSize * i;
+ const vertexPosition = new Float32Array(vertexAttributes, baseOffset, 1);
+ vertexPosition[0] = kPositions[i];
+ const vertexColor = new Uint8Array(vertexAttributes, baseOffset + 4, 4);
+ vertexColor.set(kColors[i]);
+ }
+
+ vertexBuffer.unmap();
+
+ const renderPipeline = t.GetRenderPipelineForTest(t.kVertexAttributeSize);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kPositions.length, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(renderPipeline);
+
+ // Change 'size' in setVertexBuffer()
+ renderPass.setVertexBuffer(0, vertexBuffer, 0, t.kVertexAttributeSize);
+ renderPass.setVertexBuffer(0, vertexBuffer, 0, t.kVertexAttributeSize * 2);
+ renderPass.draw(2);
+
+ // Change 'offset' in setVertexBuffer()
+ renderPass.setVertexBuffer(
+ 0,
+ vertexBuffer,
+ t.kVertexAttributeSize * 2,
+ t.kVertexAttributeSize * 2
+ );
+
+ renderPass.draw(2);
+
+ // Change 'size' again in setVertexBuffer()
+ renderPass.setVertexBuffer(
+ 0,
+ vertexBuffer,
+ t.kVertexAttributeSize * 4,
+ t.kVertexAttributeSize * 2
+ );
+
+ renderPass.setVertexBuffer(
+ 0,
+ vertexBuffer,
+ t.kVertexAttributeSize * 4,
+ t.kVertexAttributeSize * 4
+ );
+
+ renderPass.draw(4);
+
+ renderPass.end();
+ t.queue.submit([encoder.finish()]);
+
+ for (let i = 0; i < kPositions.length; ++i) {
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ 'rgba8unorm',
+ { x: i, y: 0 },
+ { exp: kColors[i] }
+ );
+ }
+ });
+
+g.test('change_pipeline_before_and_after_vertex_buffer')
+ .desc(
+ `
+ Test that changing the pipeline {before,after} the vertex buffers still keeps the correctness of
+ each draw call (In D3D12, the vertex buffer stride is part of SetVertexBuffer instead of the
+ pipeline.)
+`
+ )
+ .fn(async t => {
+ const kPositions = [-0.8, -0.4, 0.0, 0.4, 0.8, 0.9];
+ const kColors = [
+ new Uint8Array([255, 0, 0, 255]),
+ new Uint8Array([255, 255, 255, 255]),
+ new Uint8Array([0, 255, 0, 255]),
+ new Uint8Array([0, 0, 255, 255]),
+ new Uint8Array([255, 0, 255, 255]),
+ new Uint8Array([0, 255, 255, 255]),
+ ];
+
+ // Initialize the vertex buffer with required vertex attributes (position: f32, color: f32x4)
+ const vertexBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.VERTEX,
+ size: t.kVertexAttributeSize * kPositions.length,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(vertexBuffer);
+ // Note that kPositions[1], kColors[1], kPositions[5] and kColors[5] are not used.
+ const vertexAttributes = vertexBuffer.getMappedRange();
+ for (let i = 0; i < kPositions.length; ++i) {
+ const baseOffset = t.kVertexAttributeSize * i;
+ const vertexPosition = new Float32Array(vertexAttributes, baseOffset, 1);
+ vertexPosition[0] = kPositions[i];
+ const vertexColor = new Uint8Array(vertexAttributes, baseOffset + 4, 4);
+ vertexColor.set(kColors[i]);
+ }
+ vertexBuffer.unmap();
+
+ // Create two render pipelines with different vertex attribute strides
+ const renderPipeline1 = t.GetRenderPipelineForTest(t.kVertexAttributeSize);
+ const renderPipeline2 = t.GetRenderPipelineForTest(t.kVertexAttributeSize * 2);
+
+ const kPointsCount = kPositions.length - 1;
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kPointsCount, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ // Update render pipeline before setVertexBuffer. The applied vertex attribute stride should be
+ // 2 * kVertexAttributeSize.
+ renderPass.setPipeline(renderPipeline1);
+ renderPass.setPipeline(renderPipeline2);
+ renderPass.setVertexBuffer(0, vertexBuffer);
+ renderPass.draw(2);
+
+ // Update render pipeline after setVertexBuffer. The applied vertex attribute stride should be
+ // kVertexAttributeSize.
+ renderPass.setVertexBuffer(0, vertexBuffer, 3 * t.kVertexAttributeSize);
+ renderPass.setPipeline(renderPipeline1);
+ renderPass.draw(2);
+
+ renderPass.end();
+
+ t.queue.submit([encoder.finish()]);
+
+ for (let i = 0; i < kPointsCount; ++i) {
+ const expectedColor = i === 1 ? new Uint8Array([0, 0, 0, 255]) : kColors[i];
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ 'rgba8unorm',
+ { x: i, y: 0 },
+ { exp: expectedColor }
+ );
+ }
+ });
+
+g.test('set_vertex_buffer_but_not_used_in_draw')
+ .desc(
+ `
+ Test that drawing after having set vertex buffer slots not used by the pipeline works correctly.
+ - In the test there are 2 draw calls in the render pass. The first draw call uses 2 vertex buffers
+ (position and color), and the second draw call only uses 1 vertex buffer (for color, the vertex
+ position is defined as constant values in the vertex shader). The test verifies if both of these
+ two draw calls work correctly.
+ `
+ )
+ .fn(async t => {
+ const kPositions = new Float32Array([-0.75, -0.25]);
+ const kColors = new Uint8Array([255, 0, 0, 255, 0, 255, 0, 255]);
+
+ // Initialize the vertex buffers with required vertex attributes (position: f32, color: f32x4)
+ const kAttributeStride = 4;
+ const positionBuffer = t.makeBufferWithContents(kPositions, GPUBufferUsage.VERTEX);
+ const colorBuffer = t.makeBufferWithContents(kColors, GPUBufferUsage.VERTEX);
+
+ const fragmentState = {
+ module: t.device.createShaderModule({
+ code: `
+ struct Input {
+ @location(0) color : vec4<f32>
+ };
+ @fragment
+ fn main(input : Input) -> @location(0) vec4<f32> {
+ return input.color;
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ };
+
+ // Create renderPipeline1 that uses both positionBuffer and colorBuffer.
+ const renderPipeline1 = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Inputs {
+ @location(0) vertexColor : vec4<f32>,
+ @location(1) vertexPosition : f32,
+ };
+ struct Outputs {
+ @builtin(position) position : vec4<f32>,
+ @location(0) color : vec4<f32>,
+ };
+ @vertex
+ fn main(input : Inputs)-> Outputs {
+ var outputs : Outputs;
+ outputs.position =
+ vec4<f32>(input.vertexPosition, 0.5, 0.0, 1.0);
+ outputs.color = input.vertexColor;
+ return outputs;
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ arrayStride: kAttributeStride,
+ attributes: [
+ {
+ format: 'unorm8x4',
+ offset: 0,
+ shaderLocation: 0,
+ },
+ ],
+ },
+ {
+ arrayStride: kAttributeStride,
+ attributes: [
+ {
+ format: 'float32',
+ offset: 0,
+ shaderLocation: 1,
+ },
+ ],
+ },
+ ],
+ },
+ fragment: fragmentState,
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const renderPipeline2 = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Inputs {
+ @builtin(vertex_index) vertexIndex : u32,
+ @location(0) vertexColor : vec4<f32>,
+ };
+ struct Outputs {
+ @builtin(position) position : vec4<f32>,
+ @location(0) color : vec4<f32>,
+ };
+ @vertex
+ fn main(input : Inputs)-> Outputs {
+ var kPositions = array<f32, 2> (0.25, 0.75);
+ var outputs : Outputs;
+ outputs.position =
+ vec4(kPositions[input.vertexIndex], 0.5, 0.0, 1.0);
+ outputs.color = input.vertexColor;
+ return outputs;
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ arrayStride: kAttributeStride,
+ attributes: [
+ {
+ format: 'unorm8x4',
+ offset: 0,
+ shaderLocation: 0,
+ },
+ ],
+ },
+ ],
+ },
+ fragment: fragmentState,
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const kPointsCount = 4;
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kPointsCount, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ renderPass.setVertexBuffer(0, colorBuffer);
+ renderPass.setVertexBuffer(1, positionBuffer);
+ renderPass.setPipeline(renderPipeline1);
+ renderPass.draw(2);
+
+ renderPass.setPipeline(renderPipeline2);
+ renderPass.draw(2);
+
+ renderPass.end();
+
+ t.queue.submit([encoder.finish()]);
+
+ const kExpectedColors = [
+ kColors.subarray(0, 4),
+ kColors.subarray(4),
+ kColors.subarray(0, 4),
+ kColors.subarray(4),
+ ];
+
+ for (let i = 0; i < kPointsCount; ++i) {
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ 'rgba8unorm',
+ { x: i, y: 0 },
+ { exp: kExpectedColors[i] }
+ );
+ }
+ });
+
+g.test('set_index_buffer_before_non_indexed_draw')
+ .desc(
+ `
+ Test that setting / not setting the index buffer does not impact a non-indexed draw.
+ `
+ )
+ .fn(async t => {
+ const kPositions = [-0.75, -0.25, 0.25, 0.75];
+ const kColors = [
+ new Uint8Array([255, 0, 0, 255]),
+ new Uint8Array([0, 255, 0, 255]),
+ new Uint8Array([0, 0, 255, 255]),
+ new Uint8Array([255, 0, 255, 255]),
+ ];
+
+ // Initialize the vertex buffer with required vertex attributes (position: f32, color: f32x4)
+ const vertexBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.VERTEX,
+ size: t.kVertexAttributeSize * kPositions.length,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(vertexBuffer);
+ const vertexAttributes = vertexBuffer.getMappedRange();
+ for (let i = 0; i < kPositions.length; ++i) {
+ const baseOffset = t.kVertexAttributeSize * i;
+ const vertexPosition = new Float32Array(vertexAttributes, baseOffset, 1);
+ vertexPosition[0] = kPositions[i];
+ const vertexColor = new Uint8Array(vertexAttributes, baseOffset + 4, 4);
+ vertexColor.set(kColors[i]);
+ }
+ vertexBuffer.unmap();
+
+ // Initialize the index buffer with 2 uint16 indices (2, 3).
+ const indexBuffer = t.makeBufferWithContents(new Uint16Array([2, 3]), GPUBufferUsage.INDEX);
+
+ const renderPipeline = t.GetRenderPipelineForTest(t.kVertexAttributeSize);
+
+ const kPointsCount = 4;
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kPointsCount, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ // The first draw call is an indexed one (the third and fourth color are involved)
+ renderPass.setVertexBuffer(0, vertexBuffer);
+ renderPass.setIndexBuffer(indexBuffer, 'uint16');
+ renderPass.setPipeline(renderPipeline);
+ renderPass.drawIndexed(2);
+
+ // The second draw call is a non-indexed one (the first and second color are involved)
+ renderPass.draw(2);
+
+ renderPass.end();
+
+ t.queue.submit([encoder.finish()]);
+
+ for (let i = 0; i < kPointsCount; ++i) {
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ 'rgba8unorm',
+ { x: i, y: 0 },
+ { exp: kColors[i] }
+ );
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute/basic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute/basic.spec.js
new file mode 100644
index 0000000000..391e0ad524
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute/basic.spec.js
@@ -0,0 +1,166 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Basic command buffer compute tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kLimitInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsEqualGenerated } from '../../../util/check_contents.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const kMaxComputeWorkgroupSize = [
+ kLimitInfo.maxComputeWorkgroupSizeX.default,
+ kLimitInfo.maxComputeWorkgroupSizeY.default,
+ kLimitInfo.maxComputeWorkgroupSizeZ.default,
+];
+
+g.test('memcpy').fn(async t => {
+ const data = new Uint32Array([0x01020304]);
+
+ const src = t.makeBufferWithContents(data, GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE);
+
+ const dst = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Data {
+ value : u32
+ };
+
+ @group(0) @binding(0) var<storage, read> src : Data;
+ @group(0) @binding(1) var<storage, read_write> dst : Data;
+
+ @compute @workgroup_size(1) fn main() {
+ dst.value = src.value;
+ return;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [
+ { binding: 0, resource: { buffer: src, offset: 0, size: 4 } },
+ { binding: 1, resource: { buffer: dst, offset: 0, size: 4 } },
+ ],
+
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bg);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(dst, data);
+});
+
+g.test('large_dispatch')
+ .desc(`Test reasonably-sized large dispatches (see also: stress tests).`)
+ .params(u =>
+ u
+ // Reasonably-sized powers of two, and some stranger larger sizes.
+ .combine('dispatchSize', [
+ 256,
+ 2048,
+ 315,
+ 628,
+ 2179,
+ kLimitInfo.maxComputeWorkgroupsPerDimension.default,
+ ])
+
+ // Test some reasonable workgroup sizes.
+ .beginSubcases()
+ // 0 == x axis; 1 == y axis; 2 == z axis.
+ .combine('largeDimension', [0, 1, 2])
+ .expand('workgroupSize', p => [1, 2, 8, 32, kMaxComputeWorkgroupSize[p.largeDimension]])
+ )
+ .fn(async t => {
+ // The output storage buffer is filled with this value.
+ const val = 0x01020304;
+ const badVal = 0xbaadf00d;
+
+ const wgSize = t.params.workgroupSize;
+ const bufferLength = t.params.dispatchSize * wgSize;
+ const bufferByteSize = Uint32Array.BYTES_PER_ELEMENT * bufferLength;
+ const dst = t.device.createBuffer({
+ size: bufferByteSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ // Only use one large dimension and workgroup size in the dispatch
+ // call to keep the size of the test reasonable.
+ const dims = [1, 1, 1];
+ dims[t.params.largeDimension] = t.params.dispatchSize;
+ const wgSizes = [1, 1, 1];
+ wgSizes[t.params.largeDimension] = t.params.workgroupSize;
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ struct OutputBuffer {
+ value : array<u32>
+ };
+
+ @group(0) @binding(0) var<storage, read_write> dst : OutputBuffer;
+
+ @compute @workgroup_size(${wgSizes[0]}, ${wgSizes[1]}, ${wgSizes[2]})
+ fn main(
+ @builtin(global_invocation_id) GlobalInvocationID : vec3<u32>
+ ) {
+ var xExtent : u32 = ${dims[0]}u * ${wgSizes[0]}u;
+ var yExtent : u32 = ${dims[1]}u * ${wgSizes[1]}u;
+ var zExtent : u32 = ${dims[2]}u * ${wgSizes[2]}u;
+ var index : u32 = (
+ GlobalInvocationID.z * xExtent * yExtent +
+ GlobalInvocationID.y * xExtent +
+ GlobalInvocationID.x);
+ var val : u32 = ${val}u;
+ // Trivial error checking in the indexing and invocation.
+ if (GlobalInvocationID.x > xExtent ||
+ GlobalInvocationID.y > yExtent ||
+ GlobalInvocationID.z > zExtent) {
+ val = ${badVal}u;
+ }
+ dst.value[index] = val;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer: dst, offset: 0, size: bufferByteSize } }],
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bg);
+ pass.dispatchWorkgroups(dims[0], dims[1], dims[2]);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesPassCheck(dst, a => checkElementsEqualGenerated(a, i => val), {
+ type: Uint32Array,
+ typedLength: bufferLength,
+ });
+
+ dst.destroy();
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/entry_point_name.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/entry_point_name.spec.js
new file mode 100644
index 0000000000..ddd6b8850d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/entry_point_name.spec.js
@@ -0,0 +1,13 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- Test some weird but valid values for entry point name (both module and pipeline creation
+ should succeed).
+- Test using each of many entry points in the module (should succeed).
+- Test using an entry point with the wrong stage (should fail).
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/overrides.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/overrides.spec.js
new file mode 100644
index 0000000000..a323b97eff
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/compute_pipeline/overrides.spec.js
@@ -0,0 +1,505 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Compute pipeline using overridable constants test.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+class F extends GPUTest {
+ async ExpectShaderOutputWithConstants(isAsync, expected, constants, code) {
+ const dst = this.device.createBuffer({
+ size: expected.byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({
+ code,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ const promise = isAsync
+ ? this.device.createComputePipelineAsync(descriptor)
+ : Promise.resolve(this.device.createComputePipeline(descriptor));
+
+ const pipeline = await promise;
+ const bindGroup = this.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer: dst, offset: 0, size: expected.byteLength } }],
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ this.expectGPUBufferValuesEqual(dst, expected);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('basic')
+ .desc(
+ `Test that either correct constants override values or default values when no constants override value are provided at pipeline creation time are used as the output to the storage buffer.`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const count = 11;
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ new Uint32Array(range(count, i => i)),
+ {
+ c0: 0,
+ c1: 1,
+ c2: 2,
+ c3: 3,
+ // c4 is using default value
+ c5: 5,
+ c6: 6,
+ // c7 is using default value
+ c8: 8,
+ c9: 9,
+ // c10 is using default value
+ },
+ `
+ override c0: bool; // type: bool
+ override c1: bool = false; // default override
+ override c2: f32; // type: float32
+ override c3: f32 = 0.0; // default override
+ override c4: f32 = 4.0; // default
+ override c5: i32; // type: int32
+ override c6: i32 = 0; // default override
+ override c7: i32 = 7; // default
+ override c8: u32; // type: uint32
+ override c9: u32 = 0u; // default override
+ override c10: u32 = 10u; // default
+
+ struct Buf {
+ data : array<u32, ${count}>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1) fn main() {
+ buf.data[0] = u32(c0);
+ buf.data[1] = u32(c1);
+ buf.data[2] = u32(c2);
+ buf.data[3] = u32(c3);
+ buf.data[4] = u32(c4);
+ buf.data[5] = u32(c5);
+ buf.data[6] = u32(c6);
+ buf.data[7] = u32(c7);
+ buf.data[8] = u32(c8);
+ buf.data[9] = u32(c9);
+ buf.data[10] = u32(c10);
+ }
+ `
+ );
+ });
+
+g.test('numeric_id')
+ .desc(
+ `Test that correct values are used as output to the storage buffer for constants specified with numeric id instead of their names.`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ new Uint32Array([1, 2, 3]),
+ {
+ 1001: 1,
+ 1: 2,
+ // 1003 is using default value
+ },
+ `
+ @id(1001) override c1: u32; // some big numeric id
+ @id(1) override c2: u32 = 0u; // id == 1 might collide with some generated constant id
+ @id(1003) override c3: u32 = 3u; // default
+
+ struct Buf {
+ data : array<u32, 3>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1) fn main() {
+ buf.data[0] = c1;
+ buf.data[1] = c2;
+ buf.data[2] = c3;
+ }
+ `
+ );
+ });
+
+g.test('precision')
+ .desc(
+ `Test that float number precision is preserved for constants as they are used for compute shader output of the storage buffer.`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const c1 = 3.14159;
+ const c2 = 3.141592653589793238;
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ // These values will get rounded to f32 and createComputePipeline, so the values coming out from the shader won't be the exact same one as shown here.
+ new Float32Array([c1, c2]),
+ {
+ c1,
+ c2,
+ },
+ `
+ override c1: f32;
+ override c2: f32;
+
+ struct Buf {
+ data : array<f32, 2>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1) fn main() {
+ buf.data[0] = c1;
+ buf.data[1] = c2;
+ }
+ `
+ );
+ });
+
+g.test('workgroup_size')
+ .desc(
+ `Test that constants can be used as workgroup size correctly, the compute shader should write the max local invocation id to the storage buffer which is equal to the workgroup size dimension given by the constant.`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('type', ['u32', 'i32'])
+ .combine('size', [3, 16, 64])
+ .combine('v', ['x', 'y', 'z'])
+ )
+ .fn(async t => {
+ const { isAsync, type, size, v } = t.params;
+ const workgroup_size_str = v === 'x' ? 'd' : v === 'y' ? '1, d' : '1, 1, d';
+ await t.ExpectShaderOutputWithConstants(
+ isAsync,
+ new Uint32Array([size]),
+ {
+ d: size,
+ },
+ `
+ override d: ${type};
+
+ struct Buf {
+ data : array<u32, 1>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(${workgroup_size_str}) fn main(
+ @builtin(local_invocation_id) local_invocation_id : vec3<u32>
+ ) {
+ if (local_invocation_id.${v} >= u32(d - 1)) {
+ buf.data[0] = local_invocation_id.${v} + 1;
+ }
+ }
+ `
+ );
+ });
+
+g.test('shared_shader_module')
+ .desc(
+ `Test that when the same shader module is shared by different pipelines, the correct constant values are used as output to the storage buffer. The constant value should not affect other pipeline sharing the same shader module.`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const module = t.device.createShaderModule({
+ code: `
+ override a: u32;
+
+ struct Buf {
+ data : array<u32, 1>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1) fn main() {
+ buf.data[0] = a;
+ }`,
+ });
+
+ const expects = [new Uint32Array([1]), new Uint32Array([2])];
+ const buffers = [
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ ];
+
+ const descriptors = [
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main',
+ constants: {
+ a: 1,
+ },
+ },
+ },
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main',
+ constants: {
+ a: 2,
+ },
+ },
+ },
+ ];
+
+ const promises = t.params.isAsync
+ ? Promise.all([
+ t.device.createComputePipelineAsync(descriptors[0]),
+ t.device.createComputePipelineAsync(descriptors[1]),
+ ])
+ : Promise.resolve([
+ t.device.createComputePipeline(descriptors[0]),
+ t.device.createComputePipeline(descriptors[1]),
+ ]);
+
+ const pipelines = await promises;
+ const bindGroups = [
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[0], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[0].getBindGroupLayout(0),
+ }),
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[1], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[1].getBindGroupLayout(0),
+ }),
+ ];
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipelines[0]);
+ pass.setBindGroup(0, bindGroups[0]);
+ pass.dispatchWorkgroups(1);
+ pass.setPipeline(pipelines[1]);
+ pass.setBindGroup(0, bindGroups[1]);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(buffers[0], expects[0]);
+ t.expectGPUBufferValuesEqual(buffers[1], expects[1]);
+ });
+
+g.test('multi_entry_points')
+ .desc(
+ `Test that constants used for different entry points are used correctly as output to the storage buffer. They should have no impact for pipeline using entry points that doesn't reference them.`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const module = t.device.createShaderModule({
+ code: `
+ override c1: u32;
+ override c2: u32;
+ override c3: u32;
+
+ struct Buf {
+ data : array<u32, 1>
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buf : Buf;
+
+ @compute @workgroup_size(1) fn main1() {
+ buf.data[0] = c1;
+ }
+
+ @compute @workgroup_size(1) fn main2() {
+ buf.data[0] = c2;
+ }
+
+ @compute @workgroup_size(c3) fn main3() {
+ buf.data[0] = 3u;
+ }`,
+ });
+
+ const expects = [
+ new Uint32Array([1]),
+ new Uint32Array([2]),
+ new Uint32Array([3]),
+ new Uint32Array([4]),
+ ];
+
+ const buffers = [
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ t.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ }),
+ ];
+
+ const descriptors = [
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main1',
+ constants: {
+ c1: 1,
+ },
+ },
+ },
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main2',
+ constants: {
+ c2: 2,
+ },
+ },
+ },
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main3',
+ constants: {
+ // c3 is used as workgroup size
+ c3: 1,
+ },
+ },
+ },
+ {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main1',
+ constants: {
+ // assign a different value to c1
+ c1: 4,
+ },
+ },
+ },
+ ];
+
+ const promises = t.params.isAsync
+ ? Promise.all([
+ t.device.createComputePipelineAsync(descriptors[0]),
+ t.device.createComputePipelineAsync(descriptors[1]),
+ t.device.createComputePipelineAsync(descriptors[2]),
+ t.device.createComputePipelineAsync(descriptors[3]),
+ ])
+ : Promise.resolve([
+ t.device.createComputePipeline(descriptors[0]),
+ t.device.createComputePipeline(descriptors[1]),
+ t.device.createComputePipeline(descriptors[2]),
+ t.device.createComputePipeline(descriptors[3]),
+ ]);
+
+ const pipelines = await promises;
+ const bindGroups = [
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[0], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[0].getBindGroupLayout(0),
+ }),
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[1], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[1].getBindGroupLayout(0),
+ }),
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[2], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[2].getBindGroupLayout(0),
+ }),
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: buffers[3], offset: 0, size: Uint32Array.BYTES_PER_ELEMENT },
+ },
+ ],
+
+ layout: pipelines[3].getBindGroupLayout(0),
+ }),
+ ];
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipelines[0]);
+ pass.setBindGroup(0, bindGroups[0]);
+ pass.dispatchWorkgroups(1);
+ pass.setPipeline(pipelines[1]);
+ pass.setBindGroup(0, bindGroups[1]);
+ pass.dispatchWorkgroups(1);
+ pass.setPipeline(pipelines[2]);
+ pass.setBindGroup(0, bindGroups[2]);
+ pass.dispatchWorkgroups(1);
+ pass.setPipeline(pipelines[3]);
+ pass.setBindGroup(0, bindGroups[3]);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(buffers[0], expects[0]);
+ t.expectGPUBufferValuesEqual(buffers[1], expects[1]);
+ t.expectGPUBufferValuesEqual(buffers[2], expects[2]);
+ t.expectGPUBufferValuesEqual(buffers[3], expects[3]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/device/lost.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/device/lost.spec.js
new file mode 100644
index 0000000000..423c49b672
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/device/lost.spec.js
@@ -0,0 +1,93 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for GPUDevice.lost.
+`;
+import { Fixture } from '../../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { attemptGarbageCollection } from '../../../../common/util/collect_garbage.js';
+import { getGPU } from '../../../../common/util/navigator_gpu.js';
+import {
+ assert,
+ assertNotSettledWithinTime,
+ raceWithRejectOnTimeout,
+} from '../../../../common/util/util.js';
+
+class DeviceLostTests extends Fixture {
+ // Default timeout for waiting for device lost is 2 seconds.
+ kDeviceLostTimeoutMS = 2000;
+
+ getDeviceLostWithTimeout(lost) {
+ return raceWithRejectOnTimeout(lost, this.kDeviceLostTimeoutMS, 'device was not lost');
+ }
+
+ expectDeviceDestroyed(device) {
+ this.eventualAsyncExpectation(async niceStack => {
+ try {
+ const lost = await this.getDeviceLostWithTimeout(device.lost);
+ this.expect(lost.reason === 'destroyed', 'device was lost from destroy');
+ } catch (ex) {
+ niceStack.message = 'device was not lost';
+ this.rec.expectationFailed(niceStack);
+ }
+ });
+ }
+}
+
+export const g = makeTestGroup(DeviceLostTests);
+
+g.test('not_lost_on_gc')
+ .desc(
+ `'lost' is never resolved by GPUDevice being garbage collected (with attemptGarbageCollection).`
+ )
+ .fn(async t => {
+ // Wraps a lost promise object creation in a function scope so that the device has the best
+ // chance of being gone and ready for GC before trying to resolve the lost promise.
+ const { lost } = await (async () => {
+ const adapter = await getGPU().requestAdapter();
+ assert(adapter !== null);
+ const lost = (await adapter.requestDevice()).lost;
+ return { lost };
+ })();
+ await assertNotSettledWithinTime(lost, t.kDeviceLostTimeoutMS, 'device was unexpectedly lost');
+
+ await attemptGarbageCollection();
+ });
+
+g.test('lost_on_destroy')
+ .desc(`'lost' is resolved, with reason='destroyed', on GPUDevice.destroy().`)
+ .fn(async t => {
+ const adapter = await getGPU().requestAdapter();
+ assert(adapter !== null);
+ const device = await adapter.requestDevice();
+ t.expectDeviceDestroyed(device);
+ device.destroy();
+ });
+
+g.test('same_object')
+ .desc(`'lost' provides the same Promise and GPUDeviceLostInfo objects each time it's accessed.`)
+ .fn(async t => {
+ const adapter = await getGPU().requestAdapter();
+ assert(adapter !== null);
+ const device = await adapter.requestDevice();
+
+ // The promises should be the same promise object.
+ const lostPromise1 = device.lost;
+ const lostPromise2 = device.lost;
+ t.expect(lostPromise1 === lostPromise2);
+
+ // Promise object should still be the same after destroy.
+ device.destroy();
+ const lostPromise3 = device.lost;
+ t.expect(lostPromise1 === lostPromise3);
+
+ // The results should also be the same result object.
+ const lost1 = await t.getDeviceLostWithTimeout(lostPromise1);
+ const lost2 = await t.getDeviceLostWithTimeout(lostPromise2);
+ const lost3 = await t.getDeviceLostWithTimeout(lostPromise3);
+ // Promise object should still be the same after we've been notified about device loss.
+ const lostPromise4 = device.lost;
+ t.expect(lostPromise1 === lostPromise4);
+ const lost4 = await t.getDeviceLostWithTimeout(lostPromise4);
+ t.expect(lost1 === lost2 && lost2 === lost3 && lost3 === lost4);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/labels.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/labels.spec.js
new file mode 100644
index 0000000000..3584308e66
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/labels.spec.js
@@ -0,0 +1,13 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for object labels.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('object_has_descriptor_label')
+ .desc(`For every create function, the descriptor.label is carried over to the object.label.`)
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.js
new file mode 100644
index 0000000000..e6196c7f60
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.js
@@ -0,0 +1,871 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../../../common/util/util.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { checkElementsEqualEither } from '../../../../util/check_contents.js';
+
+export const kAllWriteOps = ['storage', 'b2b-copy', 't2b-copy', 'write-buffer'];
+
+export const kAllReadOps = [
+ 'input-vertex',
+ 'input-index',
+ 'input-indirect',
+ 'input-indirect-index',
+ 'input-indirect-dispatch',
+
+ 'constant-uniform',
+
+ 'storage-read',
+
+ 'b2b-copy',
+ 'b2t-copy',
+];
+
+const kOpInfo = {
+ 'write-buffer': {
+ contexts: ['queue'],
+ },
+ 'b2t-copy': {
+ contexts: ['command-encoder'],
+ },
+ 'b2b-copy': {
+ contexts: ['command-encoder'],
+ },
+ 't2b-copy': {
+ contexts: ['command-encoder'],
+ },
+ storage: {
+ contexts: ['compute-pass-encoder', 'render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'storage-read': {
+ contexts: ['compute-pass-encoder', 'render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'input-vertex': {
+ contexts: ['render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'input-index': {
+ contexts: ['render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'input-indirect': {
+ contexts: ['render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'input-indirect-index': {
+ contexts: ['render-pass-encoder', 'render-bundle-encoder'],
+ },
+ 'input-indirect-dispatch': {
+ contexts: ['compute-pass-encoder'],
+ },
+ 'constant-uniform': {
+ contexts: ['render-pass-encoder', 'render-bundle-encoder'],
+ },
+};
+
+export function checkOpsValidForContext(ops, context) {
+ const valid =
+ kOpInfo[ops[0]].contexts.includes(context[0]) && kOpInfo[ops[1]].contexts.includes(context[1]);
+ if (!valid) return false;
+
+ if (
+ context[0] === 'render-bundle-encoder' ||
+ context[0] === 'render-pass-encoder' ||
+ context[1] === 'render-bundle-encoder' ||
+ context[1] === 'render-pass-encoder'
+ ) {
+ // In a render pass, it is invalid to use a resource as both writable and another usage.
+ // Also, for storage+storage usage, the application is opting into racy behavior.
+ // The storage+storage case is also skipped as the results cannot be reliably tested.
+ const checkImpl = (op1, op2) => {
+ switch (op1) {
+ case 'storage':
+ switch (op2) {
+ case 'storage':
+ case 'storage-read':
+ case 'input-vertex':
+ case 'input-index':
+ case 'input-indirect':
+ case 'input-indirect-index':
+ case 'constant-uniform':
+ // Write+other, or racy.
+ return false;
+ case 'b2t-copy':
+ case 't2b-copy':
+ case 'b2b-copy':
+ case 'write-buffer':
+ // These don't occur in a render pass.
+ return true;
+ }
+
+ break;
+ case 'input-vertex':
+ case 'input-index':
+ case 'input-indirect':
+ case 'input-indirect-index':
+ case 'constant-uniform':
+ case 'b2t-copy':
+ case 't2b-copy':
+ case 'b2b-copy':
+ case 'write-buffer':
+ // These are not write usages, or don't occur in a render pass.
+ break;
+ }
+
+ return true;
+ };
+ return checkImpl(ops[0], ops[1]) && checkImpl(ops[1], ops[0]);
+ }
+ return true;
+}
+
+const kDummyVertexShader = `
+@vertex fn vert_main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.5, 0.5, 0.0, 1.0);
+}
+`;
+
+// Note: If it would be useful to have any of these helpers be separate from the fixture,
+// they can be refactored into standalone functions.
+export class BufferSyncTest extends GPUTest {
+ // Vertex and index buffers used in read render pass
+
+ // Temp buffer and texture with values for buffer/texture copy write op
+ // There can be at most 2 write op
+ tmpValueBuffers = [undefined, undefined];
+ tmpValueTextures = [undefined, undefined];
+
+ // These intermediate buffers/textures are created before any read/write op
+ // to avoid extra memory synchronization between ops introduced by await on buffer/texture creations.
+ // Create extra buffers/textures needed by write operation
+ async createIntermediateBuffersAndTexturesForWriteOp(writeOp, slot, value) {
+ switch (writeOp) {
+ case 'b2b-copy':
+ this.tmpValueBuffers[slot] = await this.createBufferWithValue(value);
+ break;
+ case 't2b-copy':
+ this.tmpValueTextures[slot] = await this.createTextureWithValue(value);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Create extra buffers/textures needed by read operation
+ async createBuffersForReadOp(readOp, srcValue, opValue) {
+ // This helps create values that will be written into dst buffer by the readop
+ switch (readOp) {
+ case 'input-index':
+ // The index buffer will be the src buffer of the read op.
+ // The src value for readOp will be 0
+ // If the index buffer value is 0, the src value is written into the dst buffer.
+ // If the index buffer value is 1, the op value is written into the dst buffer.
+ this.vertexBuffer = await this.createBufferWithValues([srcValue, opValue]);
+ break;
+ case 'input-indirect':
+ // The indirect buffer for the draw cmd will be the src buffer of the read op.
+ // If the first value in the indirect buffer is 1, then the op value in vertex buffer will be written into dst buffer.
+ // If the first value in indirect buffer is 0, then nothing will be write into dst buffer.
+ this.vertexBuffer = await this.createBufferWithValues([opValue]);
+ break;
+ case 'input-indirect-index':
+ // The indirect buffer for draw indexed cmd will be the src buffer of the read op.
+ // If the first value in the indirect buffer is 1, then the opValue in vertex buffer will be written into dst buffer.
+ // If the first value in indirect buffer is 0, then nothing will be write into dst buffer.
+ this.vertexBuffer = await this.createBufferWithValues([opValue]);
+ this.indexBuffer = await this.createBufferWithValues([0]);
+ break;
+ default:
+ break;
+ }
+
+ let srcBuffer;
+ switch (readOp) {
+ case 'input-indirect':
+ // vertexCount = {0, 1}
+ // instanceCount = 1
+ // firstVertex = 0
+ // firstInstance = 0
+ srcBuffer = await this.createBufferWithValues([srcValue, 1, 0, 0]);
+ break;
+ case 'input-indirect-index':
+ // indexCount = {0, 1}
+ // instanceCount = 1
+ // firstIndex = 0
+ // baseVertex = 0
+ // firstInstance = 0
+ srcBuffer = await this.createBufferWithValues([srcValue, 1, 0, 0, 0]);
+ break;
+ case 'input-indirect-dispatch':
+ // workgroupCountX = {0, 1}
+ // workgroupCountY = 1
+ // workgroupCountZ = 1
+ srcBuffer = await this.createBufferWithValues([srcValue, 1, 1]);
+ break;
+ default:
+ srcBuffer = await this.createBufferWithValue(srcValue);
+ break;
+ }
+
+ const dstBuffer = this.trackForCleanup(
+ this.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage:
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.COPY_DST |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX |
+ GPUBufferUsage.INDIRECT |
+ GPUBufferUsage.UNIFORM,
+ })
+ );
+
+ return { srcBuffer, dstBuffer };
+ }
+
+ // Create a buffer with 1 uint32 element, and initialize it to a specified value.
+ async createBufferWithValue(initValue) {
+ const buffer = this.trackForCleanup(
+ this.device.createBuffer({
+ mappedAtCreation: true,
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage:
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.COPY_DST |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX |
+ GPUBufferUsage.INDIRECT |
+ GPUBufferUsage.UNIFORM,
+ })
+ );
+
+ new Uint32Array(buffer.getMappedRange()).fill(initValue);
+ buffer.unmap();
+ await this.queue.onSubmittedWorkDone();
+ return buffer;
+ }
+
+ // Create a buffer, and initialize it to the specified values.
+ async createBufferWithValues(initValues) {
+ const buffer = this.trackForCleanup(
+ this.device.createBuffer({
+ mappedAtCreation: true,
+ size: Uint32Array.BYTES_PER_ELEMENT * initValues.length,
+ usage:
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.COPY_DST |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX |
+ GPUBufferUsage.INDIRECT |
+ GPUBufferUsage.UNIFORM,
+ })
+ );
+
+ const bufferView = new Uint32Array(buffer.getMappedRange());
+ bufferView.set(initValues);
+ buffer.unmap();
+ await this.queue.onSubmittedWorkDone();
+ return buffer;
+ }
+
+ // Create a 1x1 texture, and initialize it to a specified value for all elements.
+ async createTextureWithValue(initValue) {
+ const data = new Uint32Array(1).fill(initValue);
+ const texture = this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'r32uint',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ })
+ );
+
+ this.device.queue.writeTexture(
+ { texture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ data,
+ { offset: 0, bytesPerRow: 256, rowsPerImage: 1 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ await this.queue.onSubmittedWorkDone();
+ return texture;
+ }
+
+ createBindGroup(pipeline, buffer) {
+ return this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer } }],
+ });
+ }
+
+ // Create a compute pipeline and write given data into storage buffer.
+ createStorageWriteComputePipeline(value) {
+ const wgslCompute = `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<storage, read_write> data : Data;
+ @compute @workgroup_size(1) fn main() {
+ data.a = ${value}u;
+ }
+ `;
+
+ return this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({
+ code: wgslCompute,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ }
+
+ createTrivialRenderPipeline(wgslShaders) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.vertex,
+ }),
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.fragment,
+ }),
+ entryPoint: 'frag_main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ }
+
+ // Create a render pipeline and write given data into storage buffer at fragment stage.
+ createStorageWriteRenderPipeline(value) {
+ const wgslShaders = {
+ vertex: kDummyVertexShader,
+ fragment: `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<storage, read_write> data : Data;
+ @fragment fn frag_main() -> @location(0) vec4<f32> {
+ data.a = ${value}u;
+ return vec4<f32>(); // result does't matter
+ }
+ `,
+ };
+
+ return this.createTrivialRenderPipeline(wgslShaders);
+ }
+
+ beginSimpleRenderPass(encoder) {
+ const view = this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ ).createView();
+ return encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view,
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+
+ // Write buffer via draw call in render pass. Use bundle if needed.
+ encodeWriteAsStorageBufferInRenderPass(renderer, buffer, value) {
+ const pipeline = this.createStorageWriteRenderPipeline(value);
+ const bindGroup = this.createBindGroup(pipeline, buffer);
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.draw(1, 1, 0, 0);
+ }
+
+ // Write buffer via dispatch call in compute pass.
+ encodeWriteAsStorageBufferInComputePass(pass, buffer, value) {
+ const pipeline = this.createStorageWriteComputePipeline(value);
+ const bindGroup = this.createBindGroup(pipeline, buffer);
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ }
+
+ // Write buffer via BufferToBuffer copy.
+ encodeWriteByB2BCopy(encoder, buffer, slot) {
+ const tmpBuffer = this.tmpValueBuffers[slot];
+ assert(tmpBuffer !== undefined);
+ // The write operation via b2b copy is just encoded into command encoder, it doesn't write immediately.
+ encoder.copyBufferToBuffer(tmpBuffer, 0, buffer, 0, Uint32Array.BYTES_PER_ELEMENT);
+ }
+
+ // Write buffer via TextureToBuffer copy.
+ encodeWriteByT2BCopy(encoder, buffer, slot) {
+ const tmpTexture = this.tmpValueTextures[slot];
+ assert(tmpTexture !== undefined);
+ // The write operation via t2b copy is just encoded into command encoder, it doesn't write immediately.
+ encoder.copyTextureToBuffer(
+ { texture: tmpTexture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+ }
+
+ // Write buffer via writeBuffer API on queue
+ writeByWriteBuffer(buffer, value) {
+ const data = new Uint32Array(1).fill(value);
+ this.device.queue.writeBuffer(buffer, 0, data);
+ }
+
+ // Issue write operation via render pass, compute pass, copy, etc.
+ encodeWriteOp(helper, operation, context, buffer, writeOpSlot, value) {
+ helper.ensureContext(context);
+
+ switch (operation) {
+ case 'write-buffer':
+ this.writeByWriteBuffer(buffer, value);
+ break;
+ case 'storage':
+ switch (context) {
+ case 'render-pass-encoder':
+ assert(helper.renderPassEncoder !== undefined);
+ this.encodeWriteAsStorageBufferInRenderPass(helper.renderPassEncoder, buffer, value);
+ break;
+ case 'render-bundle-encoder':
+ assert(helper.renderBundleEncoder !== undefined);
+ this.encodeWriteAsStorageBufferInRenderPass(helper.renderBundleEncoder, buffer, value);
+ break;
+ case 'compute-pass-encoder':
+ assert(helper.computePassEncoder !== undefined);
+ this.encodeWriteAsStorageBufferInComputePass(helper.computePassEncoder, buffer, value);
+ break;
+ default:
+ unreachable();
+ }
+
+ break;
+ case 'b2b-copy':
+ assert(helper.commandEncoder !== undefined);
+ this.encodeWriteByB2BCopy(helper.commandEncoder, buffer, writeOpSlot);
+ break;
+ case 't2b-copy':
+ assert(helper.commandEncoder !== undefined);
+ this.encodeWriteByT2BCopy(helper.commandEncoder, buffer, writeOpSlot);
+ break;
+ default:
+ unreachable();
+ }
+ }
+
+ // Create a compute pipeline: read from src buffer and write it into the storage buffer.
+ createStorageReadComputePipeline() {
+ const wgslCompute = `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<storage, read> srcData : Data;
+ @group(0) @binding(1) var<storage, read_write> dstData : Data;
+
+ @compute @workgroup_size(1) fn main() {
+ dstData.a = srcData.a;
+ }
+ `;
+
+ return this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({
+ code: wgslCompute,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ }
+
+ createBindGroupSrcDstBuffer(pipeline, srcBuffer, dstBuffer) {
+ return this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ { binding: 0, resource: { buffer: srcBuffer } },
+ { binding: 1, resource: { buffer: dstBuffer } },
+ ],
+ });
+ }
+
+ // Create a render pipeline: read from vertex/index buffer and write it into the storage dst buffer at fragment stage.
+ createVertexReadRenderPipeline() {
+ const wgslShaders = {
+ vertex: `
+ struct VertexOutput {
+ @builtin(position) position : vec4<f32>,
+ @location(0) @interpolate(flat) data : u32,
+ };
+
+ @vertex fn vert_main(@location(0) input: u32) -> VertexOutput {
+ var output : VertexOutput;
+ output.position = vec4<f32>(0.5, 0.5, 0.0, 1.0);
+ output.data = input;
+ return output;
+ }
+ `,
+ fragment: `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<storage, read_write> data : Data;
+
+ @fragment fn frag_main(@location(0) @interpolate(flat) input : u32) -> @location(0) vec4<f32> {
+ data.a = input;
+ return vec4<f32>(); // result does't matter
+ }
+ `,
+ };
+
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.vertex,
+ }),
+ entryPoint: 'vert_main',
+ buffers: [
+ {
+ arrayStride: Uint32Array.BYTES_PER_ELEMENT,
+ attributes: [
+ {
+ shaderLocation: 0,
+ offset: 0,
+ format: 'uint32',
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.fragment,
+ }),
+ entryPoint: 'frag_main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ }
+
+ // Create a render pipeline: read from uniform buffer and write it into the storage dst buffer at fragment stage.
+ createUniformReadRenderPipeline() {
+ const wgslShaders = {
+ vertex: kDummyVertexShader,
+ fragment: `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<uniform> constant: Data;
+ @group(0) @binding(1) var<storage, read_write> data : Data;
+
+ @fragment fn frag_main() -> @location(0) vec4<f32> {
+ data.a = constant.a;
+ return vec4<f32>(); // result does't matter
+ }
+ `,
+ };
+
+ return this.createTrivialRenderPipeline(wgslShaders);
+ }
+
+ // Create a render pipeline: read from storage src buffer and write it into the storage dst buffer at fragment stage.
+ createStorageReadRenderPipeline() {
+ const wgslShaders = {
+ vertex: kDummyVertexShader,
+ fragment: `
+ struct Data {
+ a : u32
+ };
+
+ @group(0) @binding(0) var<storage, read> srcData : Data;
+ @group(0) @binding(1) var<storage, read_write> dstData : Data;
+
+ @fragment fn frag_main() -> @location(0) vec4<f32> {
+ dstData.a = srcData.a;
+ return vec4<f32>(); // result does't matter
+ }
+ `,
+ };
+
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.vertex,
+ }),
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: wgslShaders.fragment,
+ }),
+ entryPoint: 'frag_main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ }
+
+ // Write buffer via dispatch call in compute pass.
+ encodeReadAsStorageBufferInComputePass(pass, srcBuffer, dstBuffer) {
+ const pipeline = this.createStorageReadComputePipeline();
+ const bindGroup = this.createBindGroupSrcDstBuffer(pipeline, srcBuffer, dstBuffer);
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ }
+
+ // Write buffer via dispatchWorkgroupsIndirect call in compute pass.
+ encodeReadAsIndirectBufferInComputePass(pass, srcBuffer, dstBuffer, value) {
+ const pipeline = this.createStorageWriteComputePipeline(value);
+ const bindGroup = this.createBindGroup(pipeline, dstBuffer);
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroupsIndirect(srcBuffer, 0);
+ }
+
+ // Read as vertex input and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsVertexBufferInRenderPass(renderer, srcBuffer, dstBuffer) {
+ const pipeline = this.createVertexReadRenderPipeline();
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: dstBuffer } }],
+ });
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.setVertexBuffer(0, srcBuffer);
+ renderer.draw(1);
+ }
+
+ // Read as index input and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsIndexBufferInRenderPass(renderer, srcBuffer, dstBuffer, vertexBuffer) {
+ const pipeline = this.createVertexReadRenderPipeline();
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: dstBuffer } }],
+ });
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.setVertexBuffer(0, vertexBuffer);
+ renderer.setIndexBuffer(srcBuffer, 'uint32');
+ renderer.drawIndexed(1);
+ }
+
+ // Read as indirect input and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsIndirectBufferInRenderPass(renderer, srcBuffer, dstBuffer, vertexBuffer) {
+ const pipeline = this.createVertexReadRenderPipeline();
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: dstBuffer } }],
+ });
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.setVertexBuffer(0, vertexBuffer);
+ renderer.drawIndirect(srcBuffer, 0);
+ }
+
+ // Read as indexed indirect input and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsIndexedIndirectBufferInRenderPass(
+ renderer,
+ srcBuffer,
+ dstBuffer,
+ vertexBuffer,
+ indexBuffer
+ ) {
+ const pipeline = this.createVertexReadRenderPipeline();
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: dstBuffer } }],
+ });
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.setVertexBuffer(0, vertexBuffer);
+ renderer.setIndexBuffer(indexBuffer, 'uint32');
+ renderer.drawIndexedIndirect(srcBuffer, 0);
+ }
+
+ // Read as uniform buffer and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsUniformBufferInRenderPass(renderer, srcBuffer, dstBuffer) {
+ const pipeline = this.createUniformReadRenderPipeline();
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ { binding: 0, resource: { buffer: srcBuffer } },
+ { binding: 1, resource: { buffer: dstBuffer } },
+ ],
+ });
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.draw(1);
+ }
+
+ // Read as storage buffer and write buffer via draw call in render pass. Use bundle if needed.
+ encodeReadAsStorageBufferInRenderPass(renderer, srcBuffer, dstBuffer) {
+ const pipeline = this.createStorageReadRenderPipeline();
+ const bindGroup = this.createBindGroupSrcDstBuffer(pipeline, srcBuffer, dstBuffer);
+
+ renderer.setBindGroup(0, bindGroup);
+ renderer.setPipeline(pipeline);
+ renderer.draw(1, 1, 0, 0);
+ }
+
+ // Read and write via BufferToBuffer copy.
+ encodeReadByB2BCopy(encoder, srcBuffer, dstBuffer) {
+ // The b2b copy is just encoded into command encoder, it doesn't write immediately.
+ encoder.copyBufferToBuffer(srcBuffer, 0, dstBuffer, 0, Uint32Array.BYTES_PER_ELEMENT);
+ }
+
+ // Read and Write texture via BufferToTexture copy.
+ encodeReadByB2TCopy(encoder, srcBuffer, dstBuffer) {
+ const tmpTexture = this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'r32uint',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ })
+ );
+
+ // The b2t copy is just encoded into command encoder, it doesn't write immediately.
+ encoder.copyBufferToTexture(
+ { buffer: srcBuffer, bytesPerRow: 256 },
+ { texture: tmpTexture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ // The t2b copy is just encoded into command encoder, it doesn't write immediately.
+ encoder.copyTextureToBuffer(
+ { texture: tmpTexture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dstBuffer, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+ }
+
+ encodeReadOp(helper, operation, context, srcBuffer, dstBuffer) {
+ helper.ensureContext(context);
+
+ const renderer =
+ context === 'render-bundle-encoder' ? helper.renderBundleEncoder : helper.renderPassEncoder;
+ const computePass = context === 'compute-pass-encoder' ? helper.computePassEncoder : undefined;
+
+ switch (operation) {
+ case 'input-vertex':
+ // The srcBuffer is used as vertexBuffer.
+ // draw writes the same value in srcBuffer[0] to dstBuffer[0].
+ assert(renderer !== undefined);
+ this.encodeReadAsVertexBufferInRenderPass(renderer, srcBuffer, dstBuffer);
+ break;
+ case 'input-index':
+ // The srcBuffer is used as indexBuffer.
+ // With this vertexBuffer, drawIndexed writes the same value in srcBuffer[0] to dstBuffer[0].
+ assert(renderer !== undefined);
+ assert(this.vertexBuffer !== undefined);
+ this.encodeReadAsIndexBufferInRenderPass(renderer, srcBuffer, dstBuffer, this.vertexBuffer);
+ break;
+ case 'input-indirect':
+ // The srcBuffer is used as indirectBuffer for drawIndirect.
+ // srcBuffer[0] = 0 or 1 (vertexCount), which will decide the value written into dstBuffer to be either 0 or 1.
+ assert(renderer !== undefined);
+ assert(this.vertexBuffer !== undefined);
+ this.encodeReadAsIndirectBufferInRenderPass(
+ renderer,
+ srcBuffer,
+ dstBuffer,
+ this.vertexBuffer
+ );
+
+ break;
+ case 'input-indirect-index':
+ // The srcBuffer is used as indirectBuffer for drawIndexedIndirect.
+ // srcBuffer[0] = 0 or 1 (indexCount), which will decide the value written into dstBuffer to be either 0 or 1.
+ assert(renderer !== undefined);
+ assert(this.vertexBuffer !== undefined);
+ assert(this.indexBuffer !== undefined);
+ this.encodeReadAsIndexedIndirectBufferInRenderPass(
+ renderer,
+ srcBuffer,
+ dstBuffer,
+ this.vertexBuffer,
+ this.indexBuffer
+ );
+
+ break;
+ case 'input-indirect-dispatch':
+ // The srcBuffer is used as indirectBuffer for dispatch.
+ // srcBuffer[0] = 0 or 1 (workgroupCountX), which will decide the value written into dstBuffer to be either 0 or 1.
+ assert(computePass !== undefined);
+ this.encodeReadAsIndirectBufferInComputePass(computePass, srcBuffer, dstBuffer, 1);
+ break;
+ case 'constant-uniform':
+ // The srcBuffer is used as uniform buffer.
+ assert(renderer !== undefined);
+ this.encodeReadAsUniformBufferInRenderPass(renderer, srcBuffer, dstBuffer);
+ break;
+ case 'storage-read':
+ switch (context) {
+ case 'render-pass-encoder':
+ case 'render-bundle-encoder':
+ assert(renderer !== undefined);
+ this.encodeReadAsStorageBufferInRenderPass(renderer, srcBuffer, dstBuffer);
+ break;
+ case 'compute-pass-encoder':
+ assert(computePass !== undefined);
+ this.encodeReadAsStorageBufferInComputePass(computePass, srcBuffer, dstBuffer);
+ break;
+ default:
+ unreachable();
+ }
+
+ break;
+ case 'b2b-copy':
+ assert(helper.commandEncoder !== undefined);
+ this.encodeReadByB2BCopy(helper.commandEncoder, srcBuffer, dstBuffer);
+ break;
+ case 'b2t-copy':
+ assert(helper.commandEncoder !== undefined);
+ this.encodeReadByB2TCopy(helper.commandEncoder, srcBuffer, dstBuffer);
+ break;
+ default:
+ unreachable();
+ }
+ }
+
+ verifyData(buffer, expectedValue) {
+ const bufferData = new Uint32Array(1);
+ bufferData[0] = expectedValue;
+ this.expectGPUBufferValuesEqual(buffer, bufferData);
+ }
+
+ verifyDataTwoValidValues(buffer, expectedValue1, expectedValue2) {
+ const bufferData1 = new Uint32Array(1);
+ bufferData1[0] = expectedValue1;
+ const bufferData2 = new Uint32Array(1);
+ bufferData2[0] = expectedValue2;
+ this.expectGPUBufferValuesPassCheck(
+ buffer,
+ a => checkElementsEqualEither(a, [bufferData1, bufferData2]),
+ { type: Uint32Array, typedLength: 1 }
+ );
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.js
new file mode 100644
index 0000000000..69763ab5f3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.js
@@ -0,0 +1,354 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Memory Synchronization Tests for multiple buffers: read before write, read after write, and write after write.
+
+- Create multiple src buffers and initialize it to 0, wait on the fence to ensure the data is initialized.
+Write Op: write a value (say 1) into the src buffer via render pass, copmute pass, copy, write buffer, etc.
+Read Op: read the value from the src buffer and write it to dst buffer via render pass (vertex, index, indirect input, uniform, storage), compute pass, copy etc.
+Wait on another fence, then call expectContents to verify the dst buffer value.
+ - x= write op: {storage buffer in {compute, render, render-via-bundle}, t2b copy dst, b2b copy dst, writeBuffer}
+ - x= read op: {index buffer, vertex buffer, indirect buffer (draw, draw indexed, dispatch), uniform buffer, {readonly, readwrite} storage buffer in {compute, render, render-via-bundle}, b2b copy src, b2t copy src}
+ - x= read-write sequence: {read then write, write then read, write then write}
+ - x= op context: {queue, command-encoder, compute-pass-encoder, render-pass-encoder, render-bundle-encoder}, x= op boundary: {queue-op, command-buffer, pass, execute-bundles, render-bundle}
+ - Not every context/boundary combinations are valid. We have the checkOpsValidForContext func to do the filtering.
+ - If two writes are in the same passes, render result has loose guarantees.
+
+TODO: Tests with more than one buffer to try to stress implementations a little bit more.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import {
+ kOperationBoundaries,
+ kBoundaryInfo,
+ OperationContextHelper,
+} from '../operation_context_helper.js';
+
+import {
+ kAllReadOps,
+ kAllWriteOps,
+ BufferSyncTest,
+ checkOpsValidForContext,
+} from './buffer_sync_test.js';
+
+// The src value is what stores in the src buffer before any operation.
+const kSrcValue = 0;
+// The op value is what the read/write operation write into the target buffer.
+const kOpValue = 1;
+
+export const g = makeTestGroup(BufferSyncTest);
+
+g.test('rw')
+ .desc(
+ `
+ Perform a 'read' operations on multiple buffers, followed by a 'write' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should not see the contents written by the subsequent write.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const readOp of kAllReadOps) {
+ for (const writeOp of kAllWriteOps) {
+ if (checkOpsValidForContext([readOp, writeOp], _context)) {
+ yield {
+ readOp,
+ readContext: _context[0],
+ writeOp,
+ writeContext: _context[1],
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const srcBuffers = [];
+ const dstBuffers = [];
+
+ const kBufferCount = 4;
+ for (let i = 0; i < kBufferCount; i++) {
+ const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
+ srcBuffers.push(srcBuffer);
+ dstBuffers.push(dstBuffer);
+ }
+
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);
+
+ // The read op will read from src buffers and write to dst buffers based on what it reads.
+ // A boundary will separate multiple read and write operations. The write op will write the
+ // given op value into each src buffer as well. The write op happens after read op. So we are
+ // expecting each src value to be in the mapped dst buffer.
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeReadOp(helper, readOp, readContext, srcBuffers[i], dstBuffers[i]);
+ }
+
+ helper.ensureBoundary(boundary);
+
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeWriteOp(helper, writeOp, writeContext, srcBuffers[i], 0, kOpValue);
+ }
+
+ helper.ensureSubmit();
+
+ for (let i = 0; i < kBufferCount; i++) {
+ // Only verify the value of the first element of each dstBuffer.
+ t.verifyData(dstBuffers[i], kSrcValue);
+ }
+ });
+
+g.test('wr')
+ .desc(
+ `
+ Perform a 'write' operation on on multiple buffers, followed by a 'read' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should see exactly the contents written by the previous write.`
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const readOp of kAllReadOps) {
+ for (const writeOp of kAllWriteOps) {
+ if (checkOpsValidForContext([readOp, writeOp], _context)) {
+ yield {
+ readOp,
+ readContext: _context[0],
+ writeOp,
+ writeContext: _context[1],
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const srcBuffers = [];
+ const dstBuffers = [];
+
+ const kBufferCount = 4;
+
+ for (let i = 0; i < kBufferCount; i++) {
+ const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
+
+ srcBuffers.push(srcBuffer);
+ dstBuffers.push(dstBuffer);
+ }
+
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);
+
+ // The write op will write the given op value into src buffers.
+ // The read op will read from src buffers and write to dst buffers based on what it reads.
+ // The write op happens before read op. So we are expecting the op value to be in the dst
+ // buffers.
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeWriteOp(helper, writeOp, writeContext, srcBuffers[i], 0, kOpValue);
+ }
+
+ helper.ensureBoundary(boundary);
+
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeReadOp(helper, readOp, readContext, srcBuffers[i], dstBuffers[i]);
+ }
+
+ helper.ensureSubmit();
+
+ for (let i = 0; i < kBufferCount; i++) {
+ // Only verify the value of the first element of the dstBuffer
+ t.verifyData(dstBuffers[i], kOpValue);
+ }
+ });
+
+g.test('ww')
+ .desc(
+ `
+ Perform a 'first' write operation on multiple buffers, followed by a 'second' write operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The second write should overwrite the contents of the first.`
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const firstWriteOp of kAllWriteOps) {
+ for (const secondWriteOp of kAllWriteOps) {
+ if (checkOpsValidForContext([firstWriteOp, secondWriteOp], _context)) {
+ yield {
+ writeOps: [firstWriteOp, secondWriteOp],
+ contexts: _context,
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { writeOps, contexts, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const buffers = [];
+
+ const kBufferCount = 4;
+
+ for (let i = 0; i < kBufferCount; i++) {
+ const buffer = await t.createBufferWithValue(0);
+
+ buffers.push(buffer);
+ }
+
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOps[0], 0, 1);
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOps[1], 1, 2);
+
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeWriteOp(helper, writeOps[0], contexts[0], buffers[i], 0, 1);
+ }
+
+ helper.ensureBoundary(boundary);
+
+ for (let i = 0; i < kBufferCount; i++) {
+ t.encodeWriteOp(helper, writeOps[1], contexts[1], buffers[i], 1, 2);
+ }
+
+ helper.ensureSubmit();
+
+ for (let i = 0; i < kBufferCount; i++) {
+ t.verifyData(buffers[i], 2);
+ }
+ });
+
+g.test('multiple_pairs_of_draws_in_one_render_pass')
+ .desc(
+ `
+ Test write-after-write operations on multiple buffers via the one render pass. The first write
+ will write the buffer index * 2 + 1 into all storage buffers. The second write will write the
+ buffer index * 2 + 2 into the all buffers in the same pass. Expected data in all buffers is either
+ buffer index * 2 + 1 or buffer index * 2 + 2. It may use bundle in each draw.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('firstDrawUseBundle', [false, true])
+ .combine('secondDrawUseBundle', [false, true])
+ )
+ .fn(async t => {
+ const { firstDrawUseBundle, secondDrawUseBundle } = t.params;
+
+ const encoder = t.device.createCommandEncoder();
+ const passEncoder = t.beginSimpleRenderPass(encoder);
+
+ const kBufferCount = 4;
+ const buffers = [];
+ for (let b = 0; b < kBufferCount; ++b) {
+ const buffer = await t.createBufferWithValue(0);
+ buffers.push(buffer);
+
+ const useBundle = [firstDrawUseBundle, secondDrawUseBundle];
+ for (let i = 0; i < 2; ++i) {
+ const renderEncoder = useBundle[i]
+ ? t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ })
+ : passEncoder;
+ const pipeline = t.createStorageWriteRenderPipeline(2 * b + i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ renderEncoder.setPipeline(pipeline);
+ renderEncoder.setBindGroup(0, bindGroup);
+ renderEncoder.draw(1, 1, 0, 0);
+ if (useBundle[i]) passEncoder.executeBundles([renderEncoder.finish()]);
+ }
+ }
+
+ passEncoder.end();
+ t.device.queue.submit([encoder.finish()]);
+ for (let b = 0; b < kBufferCount; ++b) {
+ t.verifyDataTwoValidValues(buffers[b], 2 * b + 1, 2 * b + 2);
+ }
+ });
+
+g.test('multiple_pairs_of_draws_in_one_render_bundle')
+ .desc(
+ `
+ Test write-after-write operations on multiple buffers via the one render bundle. The first write
+ will write the buffer index * 2 + 1 into all storage buffers. The second write will write the
+ buffer index * 2 + 2 into the all buffers in the same pass. Expected data in all buffers is either
+ buffer index * 2 + 1 or buffer index * 2 + 2.
+ `
+ )
+ .fn(async t => {
+ const encoder = t.device.createCommandEncoder();
+ const passEncoder = t.beginSimpleRenderPass(encoder);
+ const renderEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ });
+
+ const kBufferCount = 4;
+ const buffers = [];
+ for (let b = 0; b < kBufferCount; ++b) {
+ const buffer = await t.createBufferWithValue(0);
+ buffers.push(buffer);
+
+ for (let i = 0; i < 2; ++i) {
+ const pipeline = t.createStorageWriteRenderPipeline(2 * b + i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ renderEncoder.setPipeline(pipeline);
+ renderEncoder.setBindGroup(0, bindGroup);
+ renderEncoder.draw(1, 1, 0, 0);
+ }
+ }
+
+ passEncoder.executeBundles([renderEncoder.finish()]);
+ passEncoder.end();
+ t.device.queue.submit([encoder.finish()]);
+ for (let b = 0; b < kBufferCount; ++b) {
+ t.verifyDataTwoValidValues(buffers[b], 2 * b + 1, 2 * b + 2);
+ }
+ });
+
+g.test('multiple_pairs_of_dispatches_in_one_compute_pass')
+ .desc(
+ `
+ Test write-after-write operations on multiple buffers via the one compute pass. The first write
+ will write the buffer index * 2 + 1 into all storage buffers. The second write will write the
+ buffer index * 2 + 2 into the all buffers in the same pass. Expected data in all buffers is the
+ buffer index * 2 + 2.
+ `
+ )
+ .fn(async t => {
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+
+ const kBufferCount = 4;
+ const buffers = [];
+ for (let b = 0; b < kBufferCount; ++b) {
+ const buffer = await t.createBufferWithValue(0);
+ buffers.push(buffer);
+
+ for (let i = 0; i < 2; ++i) {
+ const pipeline = t.createStorageWriteComputePipeline(2 * b + i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ }
+ }
+
+ pass.end();
+
+ t.device.queue.submit([encoder.finish()]);
+ for (let b = 0; b < kBufferCount; ++b) {
+ t.verifyData(buffers[b], 2 * b + 2);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.js
new file mode 100644
index 0000000000..2ce8744489
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.js
@@ -0,0 +1,257 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Memory Synchronization Tests for Buffer: read before write, read after write, and write after write.
+
+- Create a src buffer and initialize it to 0, wait on the fence to ensure the data is initialized.
+Write Op: write a value (say 1) into the src buffer via render pass, copmute pass, copy, write buffer, etc.
+Read Op: read the value from the src buffer and write it to dst buffer via render pass (vertex, index, indirect input, uniform, storage), compute pass, copy etc.
+Wait on another fence, then call expectContents to verify the dst buffer value.
+ - x= write op: {storage buffer in {compute, render, render-via-bundle}, t2b copy dst, b2b copy dst, writeBuffer}
+ - x= read op: {index buffer, vertex buffer, indirect buffer (draw, draw indexed, dispatch), uniform buffer, {readonly, readwrite} storage buffer in {compute, render, render-via-bundle}, b2b copy src, b2t copy src}
+ - x= read-write sequence: {read then write, write then read, write then write}
+ - x= op context: {queue, command-encoder, compute-pass-encoder, render-pass-encoder, render-bundle-encoder}, x= op boundary: {queue-op, command-buffer, pass, execute-bundles, render-bundle}
+ - Not every context/boundary combinations are valid. We have the checkOpsValidForContext func to do the filtering.
+ - If two writes are in the same passes, render result has loose guarantees.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import {
+ kOperationBoundaries,
+ kBoundaryInfo,
+ OperationContextHelper,
+} from '../operation_context_helper.js';
+
+import {
+ kAllReadOps,
+ kAllWriteOps,
+ BufferSyncTest,
+ checkOpsValidForContext,
+} from './buffer_sync_test.js';
+
+// The src value is what stores in the src buffer before any operation.
+const kSrcValue = 0;
+// The op value is what the read/write operation write into the target buffer.
+const kOpValue = 1;
+
+export const g = makeTestGroup(BufferSyncTest);
+
+g.test('rw')
+ .desc(
+ `
+ Perform a 'read' operations on a buffer, followed by a 'write' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should not see the contents written by the subsequent write.`
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const readOp of kAllReadOps) {
+ for (const writeOp of kAllWriteOps) {
+ if (checkOpsValidForContext([readOp, writeOp], _context)) {
+ yield {
+ readOp,
+ readContext: _context[0],
+ writeOp,
+ writeContext: _context[1],
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);
+
+ // The read op will read from src buffer and write to dst buffer based on what it reads.
+ // The write op will write the given op value into src buffer as well.
+ // The write op happens after read op. So we are expecting the src value to be in the dst buffer.
+ t.encodeReadOp(helper, readOp, readContext, srcBuffer, dstBuffer);
+ helper.ensureBoundary(boundary);
+ t.encodeWriteOp(helper, writeOp, writeContext, srcBuffer, 0, kOpValue);
+ helper.ensureSubmit();
+ // Only verify the value of the first element of the dstBuffer
+ t.verifyData(dstBuffer, kSrcValue);
+ });
+
+g.test('wr')
+ .desc(
+ `
+ Perform a 'write' operation on a buffer, followed by a 'read' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should see exactly the contents written by the previous write.`
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const readOp of kAllReadOps) {
+ for (const writeOp of kAllWriteOps) {
+ if (checkOpsValidForContext([readOp, writeOp], _context)) {
+ yield {
+ readOp,
+ readContext: _context[0],
+ writeOp,
+ writeContext: _context[1],
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);
+
+ // The write op will write the given op value into src buffer.
+ // The read op will read from src buffer and write to dst buffer based on what it reads.
+ // The write op happens before read op. So we are expecting the op value to be in the dst buffer.
+ t.encodeWriteOp(helper, writeOp, writeContext, srcBuffer, 0, kOpValue);
+ helper.ensureBoundary(boundary);
+ t.encodeReadOp(helper, readOp, readContext, srcBuffer, dstBuffer);
+ helper.ensureSubmit();
+ // Only verify the value of the first element of the dstBuffer
+ t.verifyData(dstBuffer, kOpValue);
+ });
+
+g.test('ww')
+ .desc(
+ `
+ Perform a 'first' write operation on a buffer, followed by a 'second' write operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The second write should overwrite the contents of the first.`
+ )
+ .params(u =>
+ u //
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const firstWriteOp of kAllWriteOps) {
+ for (const secondWriteOp of kAllWriteOps) {
+ if (checkOpsValidForContext([firstWriteOp, secondWriteOp], _context)) {
+ yield {
+ writeOps: [firstWriteOp, secondWriteOp],
+ contexts: _context,
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(async t => {
+ const { writeOps, contexts, boundary } = t.params;
+ const helper = new OperationContextHelper(t);
+
+ const buffer = await t.createBufferWithValue(0);
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOps[0], 0, 1);
+ await t.createIntermediateBuffersAndTexturesForWriteOp(writeOps[1], 1, 2);
+
+ t.encodeWriteOp(helper, writeOps[0], contexts[0], buffer, 0, 1);
+ helper.ensureBoundary(boundary);
+ t.encodeWriteOp(helper, writeOps[1], contexts[1], buffer, 1, 2);
+ helper.ensureSubmit();
+ t.verifyData(buffer, 2);
+ });
+
+// Cases with loose render result guarentees.
+
+g.test('two_draws_in_the_same_render_pass')
+ .desc(
+ `Test write-after-write operations in the same render pass. The first write will write 1 into
+ a storage buffer. The second write will write 2 into the same buffer in the same pass. Expected
+ data in buffer is either 1 or 2. It may use bundle in each draw.`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('firstDrawUseBundle', [false, true])
+ .combine('secondDrawUseBundle', [false, true])
+ )
+ .fn(async t => {
+ const { firstDrawUseBundle, secondDrawUseBundle } = t.params;
+ const buffer = await t.createBufferWithValue(0);
+ const encoder = t.device.createCommandEncoder();
+ const passEncoder = t.beginSimpleRenderPass(encoder);
+
+ const useBundle = [firstDrawUseBundle, secondDrawUseBundle];
+ for (let i = 0; i < 2; ++i) {
+ const renderEncoder = useBundle[i]
+ ? t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ })
+ : passEncoder;
+ const pipeline = t.createStorageWriteRenderPipeline(i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ renderEncoder.setPipeline(pipeline);
+ renderEncoder.setBindGroup(0, bindGroup);
+ renderEncoder.draw(1, 1, 0, 0);
+ if (useBundle[i]) passEncoder.executeBundles([renderEncoder.finish()]);
+ }
+
+ passEncoder.end();
+ t.device.queue.submit([encoder.finish()]);
+ t.verifyDataTwoValidValues(buffer, 1, 2);
+ });
+
+g.test('two_draws_in_the_same_render_bundle')
+ .desc(
+ `Test write-after-write operations in the same render bundle. The first write will write 1 into
+ a storage buffer. The second write will write 2 into the same buffer in the same pass. Expected
+ data in buffer is either 1 or 2.`
+ )
+ .fn(async t => {
+ const buffer = await t.createBufferWithValue(0);
+ const encoder = t.device.createCommandEncoder();
+ const passEncoder = t.beginSimpleRenderPass(encoder);
+ const renderEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ });
+
+ for (let i = 0; i < 2; ++i) {
+ const pipeline = t.createStorageWriteRenderPipeline(i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ renderEncoder.setPipeline(pipeline);
+ renderEncoder.setBindGroup(0, bindGroup);
+ renderEncoder.draw(1, 1, 0, 0);
+ }
+
+ passEncoder.executeBundles([renderEncoder.finish()]);
+ passEncoder.end();
+ t.device.queue.submit([encoder.finish()]);
+ t.verifyDataTwoValidValues(buffer, 1, 2);
+ });
+
+g.test('two_dispatches_in_the_same_compute_pass')
+ .desc(
+ `Test write-after-write operations in the same compute pass. The first write will write 1 into
+ a storage buffer. The second write will write 2 into the same buffer in the same pass. Expected
+ data in buffer is 2.`
+ )
+ .fn(async t => {
+ const buffer = await t.createBufferWithValue(0);
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+
+ for (let i = 0; i < 2; ++i) {
+ const pipeline = t.createStorageWriteComputePipeline(i + 1);
+ const bindGroup = t.createBindGroup(pipeline, buffer);
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ }
+
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ t.verifyData(buffer, 2);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/operation_context_helper.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/operation_context_helper.js
new file mode 100644
index 0000000000..222d06fac9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/operation_context_helper.js
@@ -0,0 +1,317 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../../common/util/util.js';
+
+/**
+ * Boundary between the first operation, and the second operation.
+ */
+export const kOperationBoundaries = [
+ 'queue-op', // Operations are performed in different queue operations (submit, writeTexture).
+ 'command-buffer', // Operations are in different command buffers.
+ 'pass', // Operations are in different passes.
+ 'execute-bundles', // Operations are in different executeBundles(...) calls
+ 'render-bundle', // Operations are in different render bundles.
+ 'dispatch', // Operations are in different dispatches.
+ 'draw', // Operations are in different draws.
+];
+
+/**
+ * Context a particular operation is permitted in.
+ * These contexts should be sorted such that the first is the most top-level
+ * context, and the last is most nested (inside a render bundle, in a render pass, ...).
+ */
+export const kOperationContexts = [
+ 'queue', // Operation occurs on the GPUQueue object
+ 'command-encoder', // Operation may be encoded in a GPUCommandEncoder.
+ 'compute-pass-encoder', // Operation may be encoded in a GPUComputePassEncoder.
+ 'render-pass-encoder', // Operation may be encoded in a GPURenderPassEncoder.
+ 'render-bundle-encoder', // Operation may be encoded in a GPURenderBundleEncoder.
+];
+
+function combineContexts(as, bs) {
+ const result = [];
+ for (const a of as) {
+ for (const b of bs) {
+ result.push([a, b]);
+ }
+ }
+ return result;
+}
+
+const queueContexts = combineContexts(kOperationContexts, kOperationContexts);
+const commandBufferContexts = combineContexts(
+ kOperationContexts.filter(c => c !== 'queue'),
+ kOperationContexts.filter(c => c !== 'queue')
+);
+
+/**
+ * Mapping of OperationBoundary => to a set of OperationContext pairs.
+ * The boundary is capable of separating operations in those two contexts.
+ */
+export const kBoundaryInfo = {
+ 'queue-op': {
+ contexts: queueContexts,
+ },
+ 'command-buffer': {
+ contexts: commandBufferContexts,
+ },
+ pass: {
+ contexts: [
+ ['compute-pass-encoder', 'compute-pass-encoder'],
+ ['compute-pass-encoder', 'render-pass-encoder'],
+ ['render-pass-encoder', 'compute-pass-encoder'],
+ ['render-pass-encoder', 'render-pass-encoder'],
+ ['render-bundle-encoder', 'render-pass-encoder'],
+ ['render-pass-encoder', 'render-bundle-encoder'],
+ ['render-bundle-encoder', 'render-bundle-encoder'],
+ ],
+ },
+ 'execute-bundles': {
+ contexts: [['render-bundle-encoder', 'render-bundle-encoder']],
+ },
+ 'render-bundle': {
+ contexts: [
+ ['render-bundle-encoder', 'render-pass-encoder'],
+ ['render-pass-encoder', 'render-bundle-encoder'],
+ ['render-bundle-encoder', 'render-bundle-encoder'],
+ ],
+ },
+ dispatch: {
+ contexts: [['compute-pass-encoder', 'compute-pass-encoder']],
+ },
+ draw: {
+ contexts: [
+ ['render-pass-encoder', 'render-pass-encoder'],
+ ['render-bundle-encoder', 'render-pass-encoder'],
+ ['render-pass-encoder', 'render-bundle-encoder'],
+ ],
+ },
+};
+
+export class OperationContextHelper {
+ // We start at the queue context which is top-level.
+ currentContext = 'queue';
+
+ // Set based on the current context.
+
+ commandBuffers = [];
+ renderBundles = [];
+
+ kTextureSize = [4, 4];
+ kTextureFormat = 'rgba8unorm';
+
+ constructor(t) {
+ this.t = t;
+ this.device = t.device;
+ this.queue = t.device.queue;
+ }
+
+ // Ensure that all encoded commands are finished and submitted.
+ ensureSubmit() {
+ this.ensureContext('queue');
+ this.flushCommandBuffers();
+ }
+
+ popContext() {
+ switch (this.currentContext) {
+ case 'queue':
+ unreachable();
+ break;
+ case 'command-encoder': {
+ assert(this.commandEncoder !== undefined);
+ const commandBuffer = this.commandEncoder.finish();
+ this.commandEncoder = undefined;
+ this.currentContext = 'queue';
+ return commandBuffer;
+ }
+ case 'compute-pass-encoder':
+ assert(this.computePassEncoder !== undefined);
+ this.computePassEncoder.end();
+ this.computePassEncoder = undefined;
+ this.currentContext = 'command-encoder';
+ break;
+ case 'render-pass-encoder':
+ assert(this.renderPassEncoder !== undefined);
+ this.renderPassEncoder.end();
+ this.renderPassEncoder = undefined;
+ this.currentContext = 'command-encoder';
+ break;
+ case 'render-bundle-encoder': {
+ assert(this.renderBundleEncoder !== undefined);
+ const renderBundle = this.renderBundleEncoder.finish();
+ this.renderBundleEncoder = undefined;
+ this.currentContext = 'render-pass-encoder';
+ return renderBundle;
+ }
+ }
+
+ return null;
+ }
+
+ makeDummyAttachment() {
+ const texture = this.t.trackForCleanup(
+ this.device.createTexture({
+ format: this.kTextureFormat,
+ size: this.kTextureSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ );
+
+ return {
+ view: texture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ };
+ }
+
+ ensureContext(context) {
+ // Find the common ancestor. So we can transition from currentContext -> context.
+ const ancestorContext =
+ kOperationContexts[
+ Math.min(
+ kOperationContexts.indexOf(context),
+ kOperationContexts.indexOf(this.currentContext)
+ )
+ ];
+
+ // Pop the context until we're at the common ancestor.
+ while (this.currentContext !== ancestorContext) {
+ // About to pop the render pass encoder. Execute any outstanding render bundles.
+ if (this.currentContext === 'render-pass-encoder') {
+ this.flushRenderBundles();
+ }
+
+ const result = this.popContext();
+ if (result) {
+ if (result instanceof GPURenderBundle) {
+ this.renderBundles.push(result);
+ } else {
+ this.commandBuffers.push(result);
+ }
+ }
+ }
+
+ if (this.currentContext === context) {
+ return;
+ }
+
+ switch (context) {
+ case 'queue':
+ unreachable();
+ break;
+ case 'command-encoder':
+ assert(this.currentContext === 'queue');
+ this.commandEncoder = this.device.createCommandEncoder();
+ break;
+ case 'compute-pass-encoder':
+ switch (this.currentContext) {
+ case 'queue':
+ this.commandEncoder = this.device.createCommandEncoder();
+ // fallthrough
+ case 'command-encoder':
+ assert(this.commandEncoder !== undefined);
+ this.computePassEncoder = this.commandEncoder.beginComputePass();
+ break;
+ case 'compute-pass-encoder':
+ case 'render-bundle-encoder':
+ case 'render-pass-encoder':
+ unreachable();
+ }
+
+ break;
+ case 'render-pass-encoder':
+ switch (this.currentContext) {
+ case 'queue':
+ this.commandEncoder = this.device.createCommandEncoder();
+ // fallthrough
+ case 'command-encoder':
+ assert(this.commandEncoder !== undefined);
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass({
+ colorAttachments: [this.makeDummyAttachment()],
+ });
+ break;
+ case 'render-pass-encoder':
+ case 'render-bundle-encoder':
+ case 'compute-pass-encoder':
+ unreachable();
+ }
+
+ break;
+ case 'render-bundle-encoder':
+ switch (this.currentContext) {
+ case 'queue':
+ this.commandEncoder = this.device.createCommandEncoder();
+ // fallthrough
+ case 'command-encoder':
+ assert(this.commandEncoder !== undefined);
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass({
+ colorAttachments: [this.makeDummyAttachment()],
+ });
+ // fallthrough
+ case 'render-pass-encoder':
+ this.renderBundleEncoder = this.device.createRenderBundleEncoder({
+ colorFormats: [this.kTextureFormat],
+ });
+ break;
+ case 'render-bundle-encoder':
+ case 'compute-pass-encoder':
+ unreachable();
+ }
+
+ break;
+ }
+
+ this.currentContext = context;
+ }
+
+ flushRenderBundles() {
+ assert(this.renderPassEncoder !== undefined);
+ if (this.renderBundles.length) {
+ this.renderPassEncoder.executeBundles(this.renderBundles);
+ this.renderBundles = [];
+ }
+ }
+
+ flushCommandBuffers() {
+ if (this.commandBuffers.length) {
+ this.queue.submit(this.commandBuffers);
+ this.commandBuffers = [];
+ }
+ }
+
+ ensureBoundary(boundary) {
+ switch (boundary) {
+ case 'command-buffer':
+ this.ensureContext('queue');
+ break;
+ case 'queue-op':
+ this.ensureContext('queue');
+ // Submit any GPUCommandBuffers so the next one is in a separate submit.
+ this.flushCommandBuffers();
+ break;
+ case 'dispatch':
+ // Nothing to do to separate dispatches.
+ assert(this.currentContext === 'compute-pass-encoder');
+ break;
+ case 'draw':
+ // Nothing to do to separate draws.
+ assert(
+ this.currentContext === 'render-pass-encoder' ||
+ this.currentContext === 'render-bundle-encoder'
+ );
+
+ break;
+ case 'pass':
+ this.ensureContext('command-encoder');
+ break;
+ case 'render-bundle':
+ this.ensureContext('render-pass-encoder');
+ break;
+ case 'execute-bundles':
+ this.ensureContext('render-pass-encoder');
+ // Execute any GPURenderBundles so the next one is in a separate executeBundles.
+ this.flushRenderBundles();
+ break;
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/same_subresource.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/same_subresource.spec.js
new file mode 100644
index 0000000000..0dcd7f90af
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/same_subresource.spec.js
@@ -0,0 +1,709 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Memory Synchronization Tests for Texture: read before write, read after write, and write after write to the same subresource.
+
+- TODO: Test synchronization between multiple queues.
+- TODO: Test depth/stencil attachments.
+- TODO: Use non-solid-color texture contents [2]
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { assert, memcpy, unreachable } from '../../../../../common/util/util.js';
+
+import { GPUTest } from '../../../../gpu_test.js';
+import { align } from '../../../../util/math.js';
+import { getTextureCopyLayout } from '../../../../util/texture/layout.js';
+import { kTexelRepresentationInfo } from '../../../../util/texture/texel_data.js';
+import {
+ kOperationBoundaries,
+ kBoundaryInfo,
+ OperationContextHelper,
+} from '../operation_context_helper.js';
+
+import {
+ kAllReadOps,
+ kAllWriteOps,
+ checkOpsValidForContext,
+ kOpInfo,
+} from './texture_sync_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const fullscreenQuadWGSL = `
+ struct VertexOutput {
+ @builtin(position) Position : vec4<f32>
+ };
+
+ @vertex fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0));
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ return output;
+ }
+`;
+
+class TextureSyncTestHelper extends OperationContextHelper {
+ kTextureSize = [4, 4];
+ kTextureFormat = 'rgba8unorm';
+
+ constructor(t, textureCreationParams) {
+ super(t);
+ this.texture = t.trackForCleanup(
+ t.device.createTexture({
+ size: this.kTextureSize,
+ format: this.kTextureFormat,
+ ...textureCreationParams,
+ })
+ );
+ }
+
+ /**
+ * Perform a read operation on the test texture.
+ * @return GPUTexture copy containing the contents.
+ */
+ performReadOp({ op, in: context }) {
+ this.ensureContext(context);
+ switch (op) {
+ case 't2t-copy': {
+ const texture = this.t.trackForCleanup(
+ this.device.createTexture({
+ size: this.kTextureSize,
+ format: this.kTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ })
+ );
+
+ assert(this.commandEncoder !== undefined);
+ this.commandEncoder.copyTextureToTexture(
+ {
+ texture: this.texture,
+ },
+ { texture },
+ this.kTextureSize
+ );
+
+ return texture;
+ }
+ case 't2b-copy': {
+ const { byteLength, bytesPerRow } = getTextureCopyLayout(this.kTextureFormat, '2d', [
+ ...this.kTextureSize,
+ 1,
+ ]);
+
+ const buffer = this.t.trackForCleanup(
+ this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ })
+ );
+
+ const texture = this.t.trackForCleanup(
+ this.device.createTexture({
+ size: this.kTextureSize,
+ format: this.kTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ })
+ );
+
+ assert(this.commandEncoder !== undefined);
+ this.commandEncoder.copyTextureToBuffer(
+ {
+ texture: this.texture,
+ },
+ { buffer, bytesPerRow },
+ this.kTextureSize
+ );
+
+ this.commandEncoder.copyBufferToTexture(
+ { buffer, bytesPerRow },
+ { texture },
+ this.kTextureSize
+ );
+
+ return texture;
+ }
+ case 'sample': {
+ const texture = this.t.trackForCleanup(
+ this.device.createTexture({
+ size: this.kTextureSize,
+ format: this.kTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING,
+ })
+ );
+
+ const bindGroupLayout = this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,
+ texture: {
+ sampleType: 'unfilterable-float',
+ },
+ },
+ {
+ binding: 1,
+ visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,
+ storageTexture: {
+ access: 'write-only',
+ format: this.kTextureFormat,
+ },
+ },
+ ],
+ });
+
+ const bindGroup = this.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: this.texture.createView(),
+ },
+ {
+ binding: 1,
+ resource: texture.createView(),
+ },
+ ],
+ });
+
+ switch (context) {
+ case 'render-pass-encoder':
+ case 'render-bundle-encoder': {
+ const module = this.device.createShaderModule({
+ code: `${fullscreenQuadWGSL}
+
+ @group(0) @binding(0) var inputTex: texture_2d<f32>;
+ @group(0) @binding(1) var outputTex: texture_storage_2d<rgba8unorm, write>;
+
+ @fragment fn frag_main(@builtin(position) fragCoord: vec4<f32>) -> @location(0) vec4<f32> {
+ let coord = vec2<i32>(fragCoord.xy);
+ textureStore(outputTex, coord, textureLoad(inputTex, coord, 0));
+ return vec4<f32>();
+ }
+ `,
+ });
+ const renderPipeline = this.device.createRenderPipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ }),
+ vertex: {
+ module,
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module,
+ entryPoint: 'frag_main',
+
+ // Unused attachment since we can't use textureStore in the vertex shader.
+ // Set writeMask to zero.
+ targets: [
+ {
+ format: this.kTextureFormat,
+ writeMask: 0,
+ },
+ ],
+ },
+ });
+
+ switch (context) {
+ case 'render-bundle-encoder':
+ assert(this.renderBundleEncoder !== undefined);
+ this.renderBundleEncoder.setPipeline(renderPipeline);
+ this.renderBundleEncoder.setBindGroup(0, bindGroup);
+ this.renderBundleEncoder.draw(6);
+ break;
+ case 'render-pass-encoder':
+ assert(this.renderPassEncoder !== undefined);
+ this.renderPassEncoder.setPipeline(renderPipeline);
+ this.renderPassEncoder.setBindGroup(0, bindGroup);
+ this.renderPassEncoder.draw(6);
+ break;
+ }
+
+ break;
+ }
+ case 'compute-pass-encoder': {
+ const module = this.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var inputTex: texture_2d<f32>;
+ @group(0) @binding(1) var outputTex: texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(8, 8)
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
+ if (any(gid.xy >= vec2<u32>(textureDimensions(inputTex)))) {
+ return;
+ }
+ let coord = vec2<i32>(gid.xy);
+ textureStore(outputTex, coord, textureLoad(inputTex, coord, 0));
+ }
+ `,
+ });
+ const computePipeline = this.device.createComputePipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ }),
+ compute: {
+ module,
+ entryPoint: 'main',
+ },
+ });
+
+ assert(this.computePassEncoder !== undefined);
+ this.computePassEncoder.setPipeline(computePipeline);
+ this.computePassEncoder.setBindGroup(0, bindGroup);
+ this.computePassEncoder.dispatchWorkgroups(
+ Math.ceil(this.kTextureSize[0] / 8),
+ Math.ceil(this.kTextureSize[1] / 8)
+ );
+
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ return texture;
+ }
+ case 'b2t-copy':
+ case 'attachment-resolve':
+ case 'attachment-store':
+ unreachable();
+ }
+
+ unreachable();
+ }
+
+ performWriteOp({ op, in: context }, data) {
+ this.ensureContext(context);
+ switch (op) {
+ case 'attachment-store': {
+ assert(this.commandEncoder !== undefined);
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: this.texture.createView(),
+ // [2] Use non-solid-color texture values
+ clearValue: [data.R ?? 0, data.G ?? 0, data.B ?? 0, data.A ?? 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ this.currentContext = 'render-pass-encoder';
+ break;
+ }
+ case 'write-texture': {
+ // [2] Use non-solid-color texture values
+ const rep = kTexelRepresentationInfo[this.kTextureFormat];
+ const texelData = rep.pack(rep.encode(data));
+ const numTexels = this.kTextureSize[0] * this.kTextureSize[1];
+ const fullTexelData = new ArrayBuffer(texelData.byteLength * numTexels);
+ for (let i = 0; i < numTexels; ++i) {
+ memcpy({ src: texelData }, { dst: fullTexelData, start: i * texelData.byteLength });
+ }
+
+ this.queue.writeTexture(
+ { texture: this.texture },
+ fullTexelData,
+ {
+ bytesPerRow: texelData.byteLength * this.kTextureSize[0],
+ },
+ this.kTextureSize
+ );
+
+ break;
+ }
+ case 't2t-copy': {
+ const texture = this.device.createTexture({
+ size: this.kTextureSize,
+ format: this.kTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ // [2] Use non-solid-color texture values
+ const rep = kTexelRepresentationInfo[this.kTextureFormat];
+ const texelData = rep.pack(rep.encode(data));
+ const numTexels = this.kTextureSize[0] * this.kTextureSize[1];
+ const fullTexelData = new ArrayBuffer(texelData.byteLength * numTexels);
+ for (let i = 0; i < numTexels; ++i) {
+ memcpy({ src: texelData }, { dst: fullTexelData, start: i * texelData.byteLength });
+ }
+
+ this.queue.writeTexture(
+ { texture },
+ fullTexelData,
+ {
+ bytesPerRow: texelData.byteLength * this.kTextureSize[0],
+ },
+ this.kTextureSize
+ );
+
+ assert(this.commandEncoder !== undefined);
+ this.commandEncoder.copyTextureToTexture(
+ { texture },
+ { texture: this.texture },
+ this.kTextureSize
+ );
+
+ break;
+ }
+ case 'b2t-copy': {
+ // [2] Use non-solid-color texture values
+ const rep = kTexelRepresentationInfo[this.kTextureFormat];
+ const texelData = rep.pack(rep.encode(data));
+ const bytesPerRow = align(texelData.byteLength, 256);
+ const fullTexelData = new ArrayBuffer(bytesPerRow * this.kTextureSize[1]);
+ for (let i = 0; i < this.kTextureSize[1]; ++i) {
+ for (let j = 0; j < this.kTextureSize[0]; ++j) {
+ memcpy(
+ { src: texelData },
+ {
+ dst: fullTexelData,
+ start: i * bytesPerRow + j * texelData.byteLength,
+ }
+ );
+ }
+ }
+
+ const buffer = this.t.trackForCleanup(
+ this.device.createBuffer({
+ size: fullTexelData.byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ })
+ );
+
+ this.queue.writeBuffer(buffer, 0, fullTexelData);
+
+ assert(this.commandEncoder !== undefined);
+ this.commandEncoder.copyBufferToTexture(
+ { buffer, bytesPerRow },
+ { texture: this.texture },
+ this.kTextureSize
+ );
+
+ break;
+ }
+ case 'attachment-resolve': {
+ assert(this.commandEncoder !== undefined);
+ const renderTarget = this.t.trackForCleanup(
+ this.device.createTexture({
+ format: this.kTextureFormat,
+ size: this.kTextureSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: 4,
+ })
+ );
+
+ this.renderPassEncoder = this.commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ resolveTarget: this.texture.createView(),
+ // [2] Use non-solid-color texture values
+ clearValue: [data.R ?? 0, data.G ?? 0, data.B ?? 0, data.A ?? 0],
+ loadOp: 'clear',
+ storeOp: 'discard',
+ },
+ ],
+ });
+ this.currentContext = 'render-pass-encoder';
+ break;
+ }
+ case 'storage': {
+ const bindGroupLayout = this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,
+ storageTexture: {
+ access: 'write-only',
+ format: this.kTextureFormat,
+ },
+ },
+ ],
+ });
+
+ const bindGroup = this.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: this.texture.createView(),
+ },
+ ],
+ });
+
+ // [2] Use non-solid-color texture values
+ const storedValue = `vec4<f32>(${[data.R ?? 0, data.G ?? 0, data.B ?? 0, data.A ?? 0]
+ .map(x => x.toFixed(5))
+ .join(', ')})`;
+
+ switch (context) {
+ case 'render-pass-encoder':
+ case 'render-bundle-encoder': {
+ const module = this.device.createShaderModule({
+ code: `${fullscreenQuadWGSL}
+
+ @group(0) @binding(0) var outputTex: texture_storage_2d<rgba8unorm, write>;
+
+ @fragment fn frag_main(@builtin(position) fragCoord: vec4<f32>) -> @location(0) vec4<f32> {
+ textureStore(outputTex, vec2<i32>(fragCoord.xy), ${storedValue});
+ return vec4<f32>();
+ }
+ `,
+ });
+ const renderPipeline = this.device.createRenderPipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ }),
+ vertex: {
+ module,
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module,
+ entryPoint: 'frag_main',
+
+ // Unused attachment since we can't use textureStore in the vertex shader.
+ // Set writeMask to zero.
+ targets: [
+ {
+ format: this.kTextureFormat,
+ writeMask: 0,
+ },
+ ],
+ },
+ });
+
+ switch (context) {
+ case 'render-bundle-encoder':
+ assert(this.renderBundleEncoder !== undefined);
+ this.renderBundleEncoder.setPipeline(renderPipeline);
+ this.renderBundleEncoder.setBindGroup(0, bindGroup);
+ this.renderBundleEncoder.draw(6);
+ break;
+ case 'render-pass-encoder':
+ assert(this.renderPassEncoder !== undefined);
+ this.renderPassEncoder.setPipeline(renderPipeline);
+ this.renderPassEncoder.setBindGroup(0, bindGroup);
+ this.renderPassEncoder.draw(6);
+ break;
+ }
+
+ break;
+ }
+ case 'compute-pass-encoder': {
+ const module = this.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var outputTex: texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(8, 8)
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
+ if (any(gid.xy >= vec2<u32>(textureDimensions(outputTex)))) {
+ return;
+ }
+ let coord = vec2<i32>(gid.xy);
+ textureStore(outputTex, coord, ${storedValue});
+ }
+ `,
+ });
+ const computePipeline = this.device.createComputePipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ }),
+ compute: {
+ module,
+ entryPoint: 'main',
+ },
+ });
+
+ assert(this.computePassEncoder !== undefined);
+ this.computePassEncoder.setPipeline(computePipeline);
+ this.computePassEncoder.setBindGroup(0, bindGroup);
+ this.computePassEncoder.dispatchWorkgroups(
+ Math.ceil(this.kTextureSize[0] / 8),
+ Math.ceil(this.kTextureSize[1] / 8)
+ );
+
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ break;
+ }
+ case 't2b-copy':
+ case 'sample':
+ unreachable();
+ }
+ }
+}
+
+g.test('rw')
+ .desc(
+ `
+ Perform a 'read' operations on a texture subresource, followed by a 'write' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should not see the contents written by the subsequent write.`
+ )
+ .params(u =>
+ u
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const read of kAllReadOps) {
+ for (const write of kAllWriteOps) {
+ if (checkOpsValidForContext([read, write], _context)) {
+ yield {
+ read: { op: read, in: _context[0] },
+ write: { op: write, in: _context[1] },
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(t => {
+ const helper = new TextureSyncTestHelper(t, {
+ usage:
+ GPUTextureUsage.COPY_DST |
+ kOpInfo[t.params.read.op].readUsage |
+ kOpInfo[t.params.write.op].writeUsage,
+ });
+ // [2] Use non-solid-color texture value.
+ const texelValue1 = { R: 0, G: 1, B: 0, A: 1 };
+ const texelValue2 = { R: 1, G: 0, B: 0, A: 1 };
+
+ // Initialize the texture with something.
+ helper.performWriteOp({ op: 'write-texture', in: 'queue' }, texelValue1);
+ const readbackTexture = helper.performReadOp(t.params.read);
+ helper.ensureBoundary(t.params.boundary);
+ helper.performWriteOp(t.params.write, texelValue2);
+ helper.ensureSubmit();
+
+ // Contents should be the first value written, not the second.
+ t.expectSingleColor(readbackTexture, helper.kTextureFormat, {
+ size: [...helper.kTextureSize, 1],
+ exp: texelValue1,
+ });
+ });
+
+g.test('wr')
+ .desc(
+ `
+ Perform a 'write' operation on a texture subresource, followed by a 'read' operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The read should see exactly the contents written by the previous write.
+
+ - TODO: Use non-solid-color texture contents [2]`
+ )
+ .params(u =>
+ u
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const read of kAllReadOps) {
+ for (const write of kAllWriteOps) {
+ if (checkOpsValidForContext([write, read], _context)) {
+ yield {
+ write: { op: write, in: _context[0] },
+ read: { op: read, in: _context[1] },
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(t => {
+ const helper = new TextureSyncTestHelper(t, {
+ usage: kOpInfo[t.params.read.op].readUsage | kOpInfo[t.params.write.op].writeUsage,
+ });
+ // [2] Use non-solid-color texture value.
+ const texelValue = { R: 0, G: 1, B: 0, A: 1 };
+
+ helper.performWriteOp(t.params.write, texelValue);
+ helper.ensureBoundary(t.params.boundary);
+ const readbackTexture = helper.performReadOp(t.params.read);
+ helper.ensureSubmit();
+
+ // Contents should be exactly the values written.
+ t.expectSingleColor(readbackTexture, helper.kTextureFormat, {
+ size: [...helper.kTextureSize, 1],
+ exp: texelValue,
+ });
+ });
+
+g.test('ww')
+ .desc(
+ `
+ Perform a 'first' write operation on a texture subresource, followed by a 'second' write operation.
+ Operations are separated by a 'boundary' (pass, encoder, queue-op, etc.).
+ Test that the results are synchronized.
+ The second write should overwrite the contents of the first.`
+ )
+ .params(u =>
+ u
+ .combine('boundary', kOperationBoundaries)
+ .expand('_context', p => kBoundaryInfo[p.boundary].contexts)
+ .expandWithParams(function* ({ _context }) {
+ for (const first of kAllWriteOps) {
+ for (const second of kAllWriteOps) {
+ if (checkOpsValidForContext([first, second], _context)) {
+ yield {
+ first: { op: first, in: _context[0] },
+ second: { op: second, in: _context[1] },
+ };
+ }
+ }
+ }
+ })
+ )
+ .fn(t => {
+ const helper = new TextureSyncTestHelper(t, {
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ kOpInfo[t.params.first.op].writeUsage |
+ kOpInfo[t.params.second.op].writeUsage,
+ });
+ // [2] Use non-solid-color texture value.
+ const texelValue1 = { R: 1, G: 0, B: 0, A: 1 };
+ const texelValue2 = { R: 0, G: 1, B: 0, A: 1 };
+
+ helper.performWriteOp(t.params.first, texelValue1);
+ helper.ensureBoundary(t.params.boundary);
+ helper.performWriteOp(t.params.second, texelValue2);
+ helper.ensureSubmit();
+
+ // Read back the contents so we can test the result.
+ const readbackTexture = helper.performReadOp({ op: 't2t-copy', in: 'command-encoder' });
+ helper.ensureSubmit();
+
+ // Contents should be the second value written.
+ t.expectSingleColor(readbackTexture, helper.kTextureFormat, {
+ size: [...helper.kTextureSize, 1],
+ exp: texelValue2,
+ });
+ });
+
+g.test('rw,single_pass,load_store')
+ .desc(
+ `
+ TODO: Test memory synchronization when loading from a texture subresource in a single pass and storing to it.`
+ )
+ .unimplemented();
+
+g.test('rw,single_pass,load_resolve')
+ .desc(
+ `
+ TODO: Test memory synchronization when loading from a texture subresource in a single pass and resolving to it.`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/texture_sync_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/texture_sync_test.js
new file mode 100644
index 0000000000..35b868eaa4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/memory_sync/texture/texture_sync_test.js
@@ -0,0 +1,110 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { GPUConst } from '../../../../constants.js';
+export const kAllWriteOps = [
+ 'write-texture',
+ 'b2t-copy',
+ 't2t-copy',
+ 'storage',
+ 'attachment-store',
+ 'attachment-resolve',
+];
+
+export const kAllReadOps = ['t2b-copy', 't2t-copy', 'sample'];
+
+/**
+ * Mapping of Op to the OperationContext(s) it is valid in
+ */
+export const kOpInfo = {
+ 'write-texture': {
+ contexts: ['queue'],
+ readUsage: 0,
+ writeUsage: GPUConst.TextureUsage.COPY_DST,
+ },
+ 'b2t-copy': {
+ contexts: ['command-encoder'],
+ readUsage: 0,
+ writeUsage: GPUConst.TextureUsage.COPY_DST,
+ },
+ 't2t-copy': {
+ contexts: ['command-encoder'],
+ readUsage: GPUConst.TextureUsage.COPY_SRC,
+ writeUsage: GPUConst.TextureUsage.COPY_DST,
+ },
+ 't2b-copy': {
+ contexts: ['command-encoder'],
+ readUsage: GPUConst.TextureUsage.COPY_SRC,
+ writeUsage: 0,
+ },
+ storage: {
+ contexts: ['compute-pass-encoder', 'render-pass-encoder', 'render-bundle-encoder'],
+ readUsage: 0,
+ writeUsage: GPUConst.TextureUsage.STORAGE,
+ },
+ sample: {
+ contexts: ['compute-pass-encoder', 'render-pass-encoder', 'render-bundle-encoder'],
+ readUsage: GPUConst.TextureUsage.SAMPLED,
+ writeUsage: 0,
+ },
+ 'attachment-store': {
+ contexts: ['command-encoder'],
+ readUsage: 0,
+ writeUsage: GPUConst.TextureUsage.RENDER_ATTACHMENT,
+ },
+ 'attachment-resolve': {
+ contexts: ['command-encoder'],
+ readUsage: 0,
+ writeUsage: GPUConst.TextureUsage.RENDER_ATTACHMENT,
+ },
+};
+
+export function checkOpsValidForContext(ops, context) {
+ const valid =
+ kOpInfo[ops[0]].contexts.includes(context[0]) && kOpInfo[ops[1]].contexts.includes(context[1]);
+ if (!valid) return false;
+
+ if (
+ context[0] === 'render-bundle-encoder' ||
+ context[0] === 'render-pass-encoder' ||
+ context[1] === 'render-bundle-encoder' ||
+ context[1] === 'render-pass-encoder'
+ ) {
+ // In a render pass, it is invalid to use a resource as both writable and another usage.
+ // Also, for storage+storage usage, the application is opting into racy behavior.
+ // The storage+storage case is also skipped as the results cannot be reliably tested.
+ const checkImpl = (op1, op2) => {
+ switch (op1) {
+ case 'attachment-resolve':
+ case 'attachment-store':
+ case 'storage':
+ switch (op2) {
+ case 'attachment-resolve':
+ case 'attachment-store':
+ case 'storage':
+ case 'sample':
+ // Write+other, or racy.
+ return false;
+ case 'b2t-copy':
+ case 't2b-copy':
+ case 't2t-copy':
+ case 'write-texture':
+ // These don't occur in a render pass.
+ return true;
+ }
+
+ break;
+ case 'b2t-copy':
+ case 'sample':
+ case 't2b-copy':
+ case 't2t-copy':
+ case 'write-texture':
+ // These are not write usages, or don't occur in a render pass.
+ break;
+ }
+
+ return true;
+ };
+ return checkImpl(ops[0], ops[1]) && checkImpl(ops[1], ops[0]);
+ }
+ return true;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/onSubmittedWorkDone.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/onSubmittedWorkDone.spec.js
new file mode 100644
index 0000000000..6f549c73ad
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/onSubmittedWorkDone.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for the behavior of GPUQueue.onSubmittedWorkDone().
+
+Note that any promise timeouts will be detected by the framework.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { range } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('without_work')
+ .desc(`Await onSubmittedWorkDone once without having submitted any work.`)
+ .fn(async t => {
+ await t.queue.onSubmittedWorkDone();
+ });
+
+g.test('with_work')
+ .desc(`Await onSubmittedWorkDone once after submitting some work (writeBuffer).`)
+ .fn(async t => {
+ const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST });
+ t.queue.writeBuffer(buffer, 0, new Uint8Array(4));
+ await t.queue.onSubmittedWorkDone();
+ });
+
+g.test('many,serial')
+ .desc(`Await 1000 onSubmittedWorkDone calls in serial.`)
+ .fn(async t => {
+ for (let i = 0; i < 1000; ++i) {
+ await t.queue.onSubmittedWorkDone();
+ }
+ });
+
+g.test('many,parallel')
+ .desc(`Await 1000 onSubmittedWorkDone calls in parallel with Promise.all().`)
+ .fn(async t => {
+ const promises = range(1000, () => t.queue.onSubmittedWorkDone());
+ await Promise.all(promises);
+ });
+
+g.test('many,parallel_order')
+ .desc(`Issue 200 onSubmittedWorkDone calls and make sure they resolve in the right order.`)
+ .fn(async t => {
+ const promises = [];
+ let lastResolved = -1;
+ for (const i of range(200, i => i)) {
+ promises.push(
+ t.queue.onSubmittedWorkDone().then(() => {
+ t.expect(i === lastResolved + 1);
+ lastResolved++;
+ })
+ );
+ }
+ await Promise.all(promises);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/pipeline/default_layout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/pipeline/default_layout.spec.js
new file mode 100644
index 0000000000..7d441d2c9d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/pipeline/default_layout.spec.js
@@ -0,0 +1,28 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for default pipeline layouts.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('getBindGroupLayout_js_object')
+ .desc(
+ `Test that getBindGroupLayout returns [TODO: the same or a different, needs spec] object
+each time.`
+ )
+ .unimplemented();
+
+g.test('incompatible_with_explicit')
+ .desc(`Test that default bind group layouts are never compatible with explicitly created ones.`)
+ .unimplemented();
+
+g.test('layout')
+ .desc(
+ `Test that bind group layouts of the default pipeline layout are correct by passing various
+shaders and then checking their computed bind group layouts are compatible with particular bind
+groups.`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/queue/writeBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/queue/writeBuffer.spec.js
new file mode 100644
index 0000000000..4e59843c95
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/queue/writeBuffer.spec.js
@@ -0,0 +1,233 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = 'Operation tests for GPUQueue.writeBuffer()';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { memcpy, range } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { align } from '../../../util/math.js';
+
+const kTypedArrays = [
+ 'Uint8Array',
+ 'Uint16Array',
+ 'Uint32Array',
+ 'Int8Array',
+ 'Int16Array',
+ 'Int32Array',
+ 'Float32Array',
+ 'Float64Array',
+];
+
+class F extends GPUTest {
+ calculateRequiredBufferSize(writes) {
+ let bufferSize = 0;
+ // Calculate size of final buffer
+ for (const { bufferOffset, data, arrayType, useArrayBuffer, dataOffset, dataSize } of writes) {
+ const TypedArrayConstructor = globalThis[arrayType];
+
+ // When passing data as an ArrayBuffer, dataOffset and dataSize use byte instead of number of
+ // elements. bytesPerElement is used to convert dataOffset and dataSize from elements to bytes
+ // when useArrayBuffer === false.
+ const bytesPerElement = useArrayBuffer ? 1 : TypedArrayConstructor.BYTES_PER_ELEMENT;
+
+ // Calculate the number of bytes written to the buffer. data is always an array of elements.
+ let bytesWritten =
+ data.length * TypedArrayConstructor.BYTES_PER_ELEMENT - (dataOffset || 0) * bytesPerElement;
+
+ if (dataSize) {
+ // When defined, dataSize clamps the number of bytes written
+ bytesWritten = Math.min(bytesWritten, dataSize * bytesPerElement);
+ }
+
+ // The minimum buffer size required for the write to succeed is the number of bytes written +
+ // the bufferOffset
+ const requiredBufferSize = bufferOffset + bytesWritten;
+
+ // Find the largest required size by all writes
+ bufferSize = Math.max(bufferSize, requiredBufferSize);
+ }
+ // writeBuffer requires buffers to be a multiple of 4
+ return align(bufferSize, 4);
+ }
+
+ testWriteBuffer(...writes) {
+ const bufferSize = this.calculateRequiredBufferSize(writes);
+
+ // Initialize buffer to non-zero data (0xff) for easier debug.
+ const expectedData = new Uint8Array(bufferSize).fill(0xff);
+
+ const buffer = this.makeBufferWithContents(
+ expectedData,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ for (const { bufferOffset, data, arrayType, useArrayBuffer, dataOffset, dataSize } of writes) {
+ const TypedArrayConstructor = globalThis[arrayType];
+ const writeData = new TypedArrayConstructor(data);
+ const writeSrc = useArrayBuffer ? writeData.buffer : writeData;
+ this.queue.writeBuffer(buffer, bufferOffset, writeSrc, dataOffset, dataSize);
+ memcpy(
+ { src: writeSrc, start: dataOffset, length: dataSize },
+ { dst: expectedData, start: bufferOffset }
+ );
+ }
+
+ this.debug(`expectedData: [${expectedData.join(', ')}]`);
+ this.expectGPUBufferValuesEqual(buffer, expectedData);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kTestData = range(16, i => i);
+
+g.test('array_types')
+ .desc('Tests that writeBuffer correctly handles different TypedArrays and ArrayBuffer.')
+ .params(u =>
+ u //
+ .combine('arrayType', kTypedArrays)
+ .combine('useArrayBuffer', [false, true])
+ )
+ .fn(t => {
+ const { arrayType, useArrayBuffer } = t.params;
+ const dataOffset = 1;
+ const dataSize = 8;
+ t.testWriteBuffer({
+ bufferOffset: 0,
+ arrayType,
+ data: kTestData,
+ dataOffset,
+ dataSize,
+ useArrayBuffer,
+ });
+ });
+
+g.test('multiple_writes_at_different_offsets_and_sizes')
+ .desc(
+ `
+Tests that writeBuffer currently handles different offsets and writes. This includes:
+- Non-overlapping TypedArrays and ArrayLists
+- Overlapping TypedArrays and ArrayLists
+- Writing zero data
+- Writing on zero sized buffers
+- Unaligned source
+- Multiple overlapping writes with decreasing sizes
+ `
+ )
+ .paramsSubcasesOnly([
+ {
+ // Concatenate 2 Uint32Arrays
+ writes: [
+ {
+ bufferOffset: 0,
+ data: kTestData,
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ dataOffset: 2,
+ dataSize: 2,
+ }, // [2, 3]
+ {
+ bufferOffset: 2 * Uint32Array.BYTES_PER_ELEMENT,
+ data: kTestData,
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ dataOffset: 0,
+ dataSize: 2,
+ }, // [0, 1]
+ ], // Expected [2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
+ },
+ {
+ // Concatenate 2 Uint8Arrays
+ writes: [
+ { bufferOffset: 0, data: [0, 1, 2, 3], arrayType: 'Uint8Array', useArrayBuffer: false },
+ { bufferOffset: 4, data: [4, 5, 6, 7], arrayType: 'Uint8Array', useArrayBuffer: false },
+ ],
+ // Expected [0, 1, 2, 3, 4, 5, 6, 7]
+ },
+ {
+ // Overlap in the middle
+ writes: [
+ { bufferOffset: 0, data: kTestData, arrayType: 'Uint8Array', useArrayBuffer: false },
+ { bufferOffset: 4, data: [0], arrayType: 'Uint32Array', useArrayBuffer: false },
+ ],
+ // Expected [0, 1, 2, 3, 0, 0 ,0 ,0, 8, 9, 10, 11, 12, 13, 14, 15]
+ },
+ {
+ // Overlapping arrayLists
+ writes: [
+ {
+ bufferOffset: 0,
+ data: kTestData,
+ arrayType: 'Uint32Array',
+ useArrayBuffer: true,
+ dataOffset: 2,
+ dataSize: 4 * Uint32Array.BYTES_PER_ELEMENT,
+ },
+ { bufferOffset: 4, data: [0x04030201], arrayType: 'Uint32Array', useArrayBuffer: true },
+ ],
+ // Expected [0, 0, 1, 0, 1, 2, 3, 4, 0, 0, 3, 0, 0, 0, 4, 0]
+ },
+ {
+ // Write over with empty buffer
+ writes: [
+ { bufferOffset: 0, data: kTestData, arrayType: 'Uint8Array', useArrayBuffer: false },
+ { bufferOffset: 0, data: [], arrayType: 'Uint8Array', useArrayBuffer: false },
+ ],
+ // Expected [0, 1, 2, 3, 4, 5 ,6 ,7, 8, 9, 10, 11, 12, 13, 14, 15]
+ },
+ {
+ // Zero buffer
+ writes: [{ bufferOffset: 0, data: [], arrayType: 'Uint8Array', useArrayBuffer: false }],
+ }, // Expected []
+ {
+ // Unaligned source
+ writes: [
+ {
+ bufferOffset: 0,
+ data: [0x77, ...kTestData],
+ arrayType: 'Uint8Array',
+ useArrayBuffer: false,
+ dataOffset: 1,
+ },
+ ],
+ // Expected [0, 1, 2, 3, 4, 5 ,6 ,7, 8, 9, 10, 11, 12, 13, 14, 15]
+ },
+ {
+ // Multiple overlapping writes
+ writes: [
+ {
+ bufferOffset: 0,
+ data: [0x05050505, 0x05050505, 0x05050505, 0x05050505, 0x05050505],
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ },
+ {
+ bufferOffset: 0,
+ data: [0x04040404, 0x04040404, 0x04040404, 0x04040404],
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ },
+ {
+ bufferOffset: 0,
+ data: [0x03030303, 0x03030303, 0x03030303],
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ },
+ {
+ bufferOffset: 0,
+ data: [0x02020202, 0x02020202],
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ },
+ {
+ bufferOffset: 0,
+ data: [0x01010101],
+ arrayType: 'Uint32Array',
+ useArrayBuffer: false,
+ },
+ ],
+ // Expected [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5]
+ },
+ ])
+ .fn(t => {
+ t.testWriteBuffer(...t.params.writes);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js
new file mode 100644
index 0000000000..0e93fbdc10
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/reflection.spec.js
@@ -0,0 +1,138 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests that object attributes which reflect the object's creation properties are properly set.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { GPUConst } from '../../constants.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('buffer_reflection_attributes')
+ .desc(`For every buffer attribute, the corresponding descriptor value is carried over.`)
+ .paramsSubcasesOnly(u =>
+ u.combine('descriptor', [
+ { size: 4, usage: GPUConst.BufferUsage.VERTEX },
+ {
+ size: 16,
+ usage:
+ GPUConst.BufferUsage.STORAGE |
+ GPUConst.BufferUsage.COPY_SRC |
+ GPUConst.BufferUsage.UNIFORM,
+ },
+ { size: 32, usage: GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.COPY_DST },
+ {
+ size: 32,
+ usage: GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.MAP_WRITE,
+ invalid: true,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { descriptor } = t.params;
+
+ t.expectValidationError(() => {
+ const buffer = t.device.createBuffer(descriptor);
+
+ t.expect(buffer.size === descriptor.size);
+ t.expect(buffer.usage === descriptor.usage);
+ }, descriptor.invalid === true);
+ });
+
+g.test('texture_reflection_attributes')
+ .desc(`For every texture attribute, the corresponding descriptor value is carried over.`)
+ .paramsSubcasesOnly(u =>
+ u.combine('descriptor', [
+ {
+ size: { width: 4, height: 4 },
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ },
+ {
+ size: { width: 8, height: 8, depthOrArrayLayers: 8 },
+ format: 'bgra8unorm',
+ usage: GPUConst.TextureUsage.RENDER_ATTACHMENT | GPUConst.TextureUsage.COPY_SRC,
+ },
+ {
+ size: [4, 4],
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ mipLevelCount: 2,
+ },
+ {
+ size: [16, 16, 16],
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ dimension: '3d',
+ },
+ {
+ size: [32],
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ dimension: '1d',
+ },
+ {
+ size: { width: 4, height: 4 },
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.RENDER_ATTACHMENT,
+ sampleCount: 4,
+ },
+ {
+ size: { width: 4, height: 4 },
+ format: 'rgba8unorm',
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ sampleCount: 4,
+ invalid: true,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { descriptor } = t.params;
+
+ let width;
+ let height;
+ let depthOrArrayLayers;
+ if (Array.isArray(descriptor.size)) {
+ width = descriptor.size[0];
+ height = descriptor.size[1] || 1;
+ depthOrArrayLayers = descriptor.size[2] || 1;
+ } else {
+ width = descriptor.size.width;
+ height = descriptor.size.height || 1;
+ depthOrArrayLayers = descriptor.size.depthOrArrayLayers || 1;
+ }
+
+ t.expectValidationError(() => {
+ const texture = t.device.createTexture(descriptor);
+
+ t.expect(texture.width === width);
+ t.expect(texture.height === height);
+ t.expect(texture.depthOrArrayLayers === depthOrArrayLayers);
+ t.expect(texture.format === descriptor.format);
+ t.expect(texture.usage === descriptor.usage);
+ t.expect(texture.dimension === (descriptor.dimension || '2d'));
+ t.expect(texture.mipLevelCount === (descriptor.mipLevelCount || 1));
+ t.expect(texture.sampleCount === (descriptor.sampleCount || 1));
+ }, descriptor.invalid === true);
+ });
+
+g.test('query_set_reflection_attributes')
+ .desc(`For every queue attribute, the corresponding descriptor value is carried over.`)
+ .paramsSubcasesOnly(u =>
+ u.combine('descriptor', [
+ { type: 'occlusion', count: 4 },
+ { type: 'occlusion', count: 16 },
+ { type: 'occlusion', count: 8193, invalid: true },
+ ])
+ )
+ .fn(async t => {
+ const { descriptor } = t.params;
+
+ t.expectValidationError(() => {
+ const querySet = t.device.createQuerySet(descriptor);
+
+ t.expect(querySet.type === descriptor.type);
+ t.expect(querySet.count === descriptor.count);
+ }, descriptor.invalid === true);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/clear_value.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/clear_value.spec.js
new file mode 100644
index 0000000000..918bb90e40
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/clear_value.spec.js
@@ -0,0 +1,191 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for render pass clear values.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kDepthStencilFormats,
+ depthStencilFormatAspectSize,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stored')
+ .desc(`Test render pass clear values are stored at the end of an empty pass.`)
+ .unimplemented();
+
+g.test('loaded')
+ .desc(
+ `Test render pass clear values are visible during the pass by doing some trivial blending
+with the attachment (e.g. add [0,0,0,0] to the color and verify the stored result).`
+ )
+ .unimplemented();
+
+g.test('srgb')
+ .desc(
+ `Test that clear values on '-srgb' type attachments are interpreted as unencoded (linear),
+not decoded from srgb to linear.`
+ )
+ .unimplemented();
+
+g.test('layout')
+ .desc(
+ `Test that bind group layouts of the default pipeline layout are correct by passing various
+shaders and then checking their computed bind group layouts are compatible with particular bind
+groups.`
+ )
+ .unimplemented();
+
+g.test('stencil_clear_value')
+ .desc(
+ `Test that when stencilLoadOp is "clear", the stencil aspect should be correctly cleared by
+ GPURenderPassDepthStencilAttachment.stencilClearValue, which will be converted to the type of
+ the stencil aspect of view by taking the same number of LSBs as the number of bits in the
+ stencil aspect of one texel block of view.`
+ )
+ .params(u =>
+ u
+ .combine('stencilFormat', kDepthStencilFormats)
+ .combine('stencilClearValue', [0, 1, 0xff, 0x100 + 2, 0x10000 + 3])
+ .combine('applyStencilClearValueAsStencilReferenceValue', [true, false])
+ .filter(t => kTextureFormatInfo[t.stencilFormat].stencil)
+ )
+ .beforeAllSubcases(t => {
+ const { stencilFormat } = t.params;
+ const info = kTextureFormatInfo[stencilFormat];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ stencilFormat,
+ stencilClearValue,
+ applyStencilClearValueAsStencilReferenceValue,
+ } = t.params;
+
+ const kSize = [1, 1, 1];
+ const colorFormat = 'rgba8unorm';
+ const stencilTexture = t.device.createTexture({
+ format: stencilFormat,
+ size: kSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ const colorTexture = t.device.createTexture({
+ format: colorFormat,
+ size: kSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ const renderPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)-> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: colorFormat }],
+ },
+ depthStencil: {
+ format: stencilFormat,
+ depthCompare: 'always',
+ stencilFront: {
+ compare: 'equal',
+ },
+ stencilBack: {
+ compare: 'equal',
+ },
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ const stencilAspectSizeInBytes = depthStencilFormatAspectSize(stencilFormat, 'stencil-only');
+ assert(stencilAspectSizeInBytes > 0);
+ const expectedStencilValue = stencilClearValue & ((stencilAspectSizeInBytes << 8) - 1);
+
+ // StencilReference used in setStencilReference will also be masked to the lowest valid bits, so
+ // no matter what we set in the rest high bits that will be masked out (different or same
+ // between stencilClearValue and stencilReference), the test will pass if and only if the valid
+ // lowest bits are the same.
+ const stencilReference = applyStencilClearValueAsStencilReferenceValue
+ ? stencilClearValue
+ : expectedStencilValue;
+
+ const encoder = t.device.createCommandEncoder();
+
+ const depthStencilAttachment = {
+ view: stencilTexture.createView(),
+ stencilLoadOp: 'clear',
+ stencilStoreOp: 'store',
+ stencilClearValue,
+ };
+ if (kTextureFormatInfo[stencilFormat].depth) {
+ depthStencilAttachment.depthClearValue = 0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'store';
+ }
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'clear',
+ storeOp: 'store',
+ clearValue: [1, 0, 0, 1],
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+ renderPassEncoder.setPipeline(renderPipeline);
+ renderPassEncoder.setStencilReference(stencilReference);
+ renderPassEncoder.draw(6);
+ renderPassEncoder.end();
+
+ const destinationBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ size: 4,
+ });
+ t.trackForCleanup(destinationBuffer);
+ encoder.copyTextureToBuffer(
+ {
+ texture: stencilTexture,
+ aspect: 'stencil-only',
+ },
+ {
+ buffer: destinationBuffer,
+ },
+ [1, 1, 1]
+ );
+
+ t.queue.submit([encoder.finish()]);
+
+ t.expectSingleColor(colorTexture, colorFormat, {
+ size: [1, 1, 1],
+ exp: { R: 0, G: 1, B: 0, A: 1 },
+ });
+ t.expectGPUBufferValuesEqual(destinationBuffer, new Uint8Array([expectedStencilValue]));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/resolve.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/resolve.spec.js
new file mode 100644
index 0000000000..3a090b9510
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/resolve.spec.js
@@ -0,0 +1,206 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `API Operation Tests for RenderPass StoreOp.
+Tests a render pass with a resolveTarget resolves correctly for many combinations of:
+ - number of color attachments, some with and some without a resolveTarget
+ - renderPass storeOp set to {'store', 'discard'}
+ - resolveTarget mip level {0, >0} (TODO?: different mip level from colorAttachment)
+ - resolveTarget {2d array layer, TODO: 3d slice} {0, >0} with {2d, TODO: 3d} resolveTarget
+ (TODO?: different z from colorAttachment)
+ - TODO: test all renderable color formats
+ - TODO: test that any not-resolved attachments are rendered to correctly.
+ - TODO: test different loadOps
+ - TODO?: resolveTarget mip level {0, >0} (TODO?: different mip level from colorAttachment)
+ - TODO?: resolveTarget {2d array layer, TODO: 3d slice} {0, >0} with {2d, TODO: 3d} resolveTarget
+ (different z from colorAttachment)
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+const kSlotsToResolve = [
+ [0, 2],
+ [1, 3],
+ [0, 1, 2, 3],
+];
+
+const kSize = 4;
+const kFormat = 'rgba8unorm';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('render_pass_resolve')
+ .params(u =>
+ u
+ .combine('storeOperation', ['discard', 'store'])
+ .beginSubcases()
+ .combine('numColorAttachments', [2, 4])
+ .combine('slotsToResolve', kSlotsToResolve)
+ .combine('resolveTargetBaseMipLevel', [0, 1])
+ .combine('resolveTargetBaseArrayLayer', [0, 1])
+ )
+ .fn(t => {
+ const targets = [];
+ for (let i = 0; i < t.params.numColorAttachments; i++) {
+ targets.push({ format: kFormat });
+ }
+
+ // These shaders will draw a white triangle into a texture. After draw, the top left
+ // half of the texture will be white, and the bottom right half will be unchanged. When this
+ // texture is resolved, there will be two distinct colors in each portion of the texture, as
+ // well as a line between the portions that contain the midpoint color due to the multisample
+ // resolve.
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>( 1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Output {
+ @location(0) fragColor0 : vec4<f32>,
+ @location(1) fragColor1 : vec4<f32>,
+ @location(2) fragColor2 : vec4<f32>,
+ @location(3) fragColor3 : vec4<f32>,
+ };
+
+ @fragment fn main() -> Output {
+ return Output(
+ vec4<f32>(1.0, 1.0, 1.0, 1.0),
+ vec4<f32>(1.0, 1.0, 1.0, 1.0),
+ vec4<f32>(1.0, 1.0, 1.0, 1.0),
+ vec4<f32>(1.0, 1.0, 1.0, 1.0)
+ );
+ }`,
+ }),
+ entryPoint: 'main',
+ targets,
+ },
+ primitive: { topology: 'triangle-list' },
+ multisample: { count: 4 },
+ });
+
+ const resolveTargets = [];
+ const renderPassColorAttachments = [];
+
+ // The resolve target must be the same size as the color attachment. If we're resolving to mip
+ // level 1, the resolve target base mip level should be 2x the color attachment size.
+ const kResolveTargetSize = kSize << t.params.resolveTargetBaseMipLevel;
+
+ for (let i = 0; i < t.params.numColorAttachments; i++) {
+ const colorAttachment = t.device.createTexture({
+ format: kFormat,
+ size: { width: kSize, height: kSize, depthOrArrayLayers: 1 },
+ sampleCount: 4,
+ mipLevelCount: 1,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ if (t.params.slotsToResolve.includes(i)) {
+ const colorAttachment = t.device.createTexture({
+ format: kFormat,
+ size: { width: kSize, height: kSize, depthOrArrayLayers: 1 },
+ sampleCount: 4,
+ mipLevelCount: 1,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const resolveTarget = t.device.createTexture({
+ format: kFormat,
+ size: {
+ width: kResolveTargetSize,
+ height: kResolveTargetSize,
+ depthOrArrayLayers: t.params.resolveTargetBaseArrayLayer + 1,
+ },
+ sampleCount: 1,
+ mipLevelCount: t.params.resolveTargetBaseMipLevel + 1,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ // Clear to black for the load operation. After the draw, the top left half of the attachment
+ // will be white and the bottom right half will be black.
+ renderPassColorAttachments.push({
+ view: colorAttachment.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: t.params.storeOperation,
+ resolveTarget: resolveTarget.createView({
+ baseMipLevel: t.params.resolveTargetBaseMipLevel,
+ baseArrayLayer: t.params.resolveTargetBaseArrayLayer,
+ }),
+ });
+
+ resolveTargets.push(resolveTarget);
+ } else {
+ renderPassColorAttachments.push({
+ view: colorAttachment.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: t.params.storeOperation,
+ });
+ }
+ }
+
+ const encoder = t.device.createCommandEncoder();
+
+ const pass = encoder.beginRenderPass({
+ colorAttachments: renderPassColorAttachments,
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // Verify the resolve targets contain the correct values.
+ for (const resolveTarget of resolveTargets) {
+ // Test top left pixel, which should be {255, 255, 255, 255}.
+ t.expectSinglePixelIn2DTexture(
+ resolveTarget,
+ kFormat,
+ { x: 0, y: 0 },
+ {
+ exp: new Uint8Array([0xff, 0xff, 0xff, 0xff]),
+ slice: t.params.resolveTargetBaseArrayLayer,
+ layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
+ }
+ );
+
+ // Test bottom right pixel, which should be {0, 0, 0, 0}.
+ t.expectSinglePixelIn2DTexture(
+ resolveTarget,
+ kFormat,
+ { x: kSize - 1, y: kSize - 1 },
+ {
+ exp: new Uint8Array([0x00, 0x00, 0x00, 0x00]),
+ slice: t.params.resolveTargetBaseArrayLayer,
+ layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
+ }
+ );
+
+ // Test top right pixel, which should be {127, 127, 127, 127} due to the multisampled resolve.
+ t.expectSinglePixelBetweenTwoValuesIn2DTexture(
+ resolveTarget,
+ kFormat,
+ { x: kSize - 1, y: 0 },
+ {
+ exp: [new Uint8Array([0x7f, 0x7f, 0x7f, 0x7f]), new Uint8Array([0x80, 0x80, 0x80, 0x80])],
+ slice: t.params.resolveTargetBaseArrayLayer,
+ layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
+ }
+ );
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js
new file mode 100644
index 0000000000..c3a825dae8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js
@@ -0,0 +1,355 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `API Operation Tests for RenderPass StoreOp.
+
+ Test Coverage:
+
+ - Tests that color and depth-stencil store operations {'discard', 'store'} work correctly for a
+ render pass with both a color attachment and depth-stencil attachment.
+ TODO: use depth24plus-stencil8
+
+ - Tests that store operations {'discard', 'store'} work correctly for a render pass with multiple
+ color attachments.
+ TODO: test with more interesting loadOp values
+
+ - Tests that store operations {'discard', 'store'} work correctly for a render pass with a color
+ attachment for:
+ - All renderable color formats
+ - mip level set to {'0', mip > '0'}
+ - array layer set to {'0', layer > '1'} for 2D textures
+ TODO: depth slice set to {'0', slice > '0'} for 3D textures
+
+ - Tests that store operations {'discard', 'store'} work correctly for a render pass with a
+ depth-stencil attachment for:
+ - All renderable depth-stencil formats
+ - mip level set to {'0', mip > '0'}
+ - array layer set to {'0', layer > '1'} for 2D textures
+ TODO: test depth24plus and depth24plus-stencil8 formats
+ TODO: test that depth and stencil aspects are set separately
+ TODO: depth slice set to {'0', slice > '0'} for 3D textures
+ TODO: test with more interesting loadOp values`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kTextureFormatInfo,
+ kEncodableTextureFormats,
+ kSizedDepthStencilFormats,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+// Test with a zero and non-zero mip.
+const kMipLevel = [0, 1];
+const kMipLevelCount = 2;
+
+// Test with different numbers of color attachments.
+
+const kNumColorAttachments = [1, 2, 3, 4];
+
+// Test with a zero and non-zero array layer.
+const kArrayLayers = [0, 1];
+
+const kStoreOps = ['discard', 'store'];
+
+const kHeight = 2;
+const kWidth = 2;
+
+export const g = makeTestGroup(GPUTest);
+
+// Tests a render pass with both a color and depth stencil attachment to ensure store operations are
+// set independently.
+g.test('render_pass_store_op,color_attachment_with_depth_stencil_attachment')
+ .params(u =>
+ u //
+ .combine('colorStoreOperation', kStoreOps)
+ .combine('depthStencilStoreOperation', kStoreOps)
+ )
+ .fn(t => {
+ // Create a basic color attachment.
+ const kColorFormat = 'rgba8unorm';
+ const colorAttachment = t.device.createTexture({
+ format: kColorFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const colorAttachmentView = colorAttachment.createView();
+
+ // Create a basic depth/stencil attachment.
+ const kDepthStencilFormat = 'depth32float';
+ const depthStencilAttachment = t.device.createTexture({
+ format: kDepthStencilFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ // Color load operation will clear to {1.0, 1.0, 1.0, 1.0}.
+ // Depth operation will clear to 1.0.
+ // Store operations are determined by test the params.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: t.params.colorStoreOperation,
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: depthStencilAttachment.createView(),
+ depthClearValue: 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: t.params.depthStencilStoreOperation,
+ },
+ });
+ pass.end();
+
+ t.device.queue.submit([encoder.finish()]);
+
+ // Check that the correct store operation occurred.
+ let expectedColorValue = {};
+ if (t.params.colorStoreOperation === 'discard') {
+ // If colorStoreOp was clear, the texture should now contain {0.0, 0.0, 0.0, 0.0}.
+ expectedColorValue = { R: 0.0, G: 0.0, B: 0.0, A: 0.0 };
+ } else if (t.params.colorStoreOperation === 'store') {
+ // If colorStoreOP was store, the texture should still contain {1.0, 1.0, 1.0, 1.0}.
+ expectedColorValue = { R: 1.0, G: 1.0, B: 1.0, A: 1.0 };
+ }
+ t.expectSingleColor(colorAttachment, kColorFormat, {
+ size: [kHeight, kWidth, 1],
+ exp: expectedColorValue,
+ });
+
+ // Check that the correct store operation occurred.
+ let expectedDepthValue = {};
+ if (t.params.depthStencilStoreOperation === 'discard') {
+ // If depthStencilStoreOperation was clear, the texture's depth component should be 0.0, and
+ // the stencil component should be 0.0.
+ expectedDepthValue = { Depth: 0.0 };
+ } else if (t.params.depthStencilStoreOperation === 'store') {
+ // If depthStencilStoreOperation was store, the texture's depth component should be 1.0, and
+ // the stencil component should be 1.0.
+ expectedDepthValue = { Depth: 1.0 };
+ }
+ t.expectSingleColor(depthStencilAttachment, kDepthStencilFormat, {
+ size: [kHeight, kWidth, 1],
+ exp: expectedDepthValue,
+ layout: { mipLevel: 0, aspect: 'depth-only' },
+ });
+ });
+
+// Tests that render pass color attachment store operations work correctly for all renderable color
+// formats, mip levels and array layers.
+g.test('render_pass_store_op,color_attachment_only')
+ .params(u =>
+ u
+ .combine('colorFormat', kEncodableTextureFormats)
+ // Filter out any non-renderable formats
+ .filter(({ colorFormat }) => {
+ const info = kTextureFormatInfo[colorFormat];
+ return info.color && info.renderable;
+ })
+ .combine('storeOperation', kStoreOps)
+ .beginSubcases()
+ .combine('mipLevel', kMipLevel)
+ .combine('arrayLayer', kArrayLayers)
+ )
+ .fn(t => {
+ const colorAttachment = t.device.createTexture({
+ format: t.params.colorFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: t.params.arrayLayer + 1 },
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const colorViewDesc = {
+ baseArrayLayer: t.params.arrayLayer,
+ baseMipLevel: t.params.mipLevel,
+ mipLevelCount: 1,
+ arrayLayerCount: 1,
+ };
+
+ const colorAttachmentView = colorAttachment.createView(colorViewDesc);
+
+ // Color load operation will clear to {1.0, 0.0, 0.0, 1.0}.
+ // Color store operation is determined by the test params.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: t.params.storeOperation,
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // Check that the correct store operation occurred.
+ let expectedValue = {};
+ if (t.params.storeOperation === 'discard') {
+ // If colorStoreOp was clear, the texture should now contain {0.0, 0.0, 0.0, 0.0}.
+ expectedValue = { R: 0.0, G: 0.0, B: 0.0, A: 0.0 };
+ } else if (t.params.storeOperation === 'store') {
+ // If colorStoreOP was store, the texture should still contain {1.0, 0.0, 0.0, 1.0}.
+ expectedValue = { R: 1.0, G: 0.0, B: 0.0, A: 1.0 };
+ }
+
+ t.expectSingleColor(colorAttachment, t.params.colorFormat, {
+ size: [kHeight, kWidth, 1],
+ slice: t.params.arrayLayer,
+ exp: expectedValue,
+ layout: { mipLevel: t.params.mipLevel },
+ });
+ });
+
+// Test with multiple color attachments to ensure each attachment's storeOp is set independently.
+g.test('render_pass_store_op,multiple_color_attachments')
+ .params(u =>
+ u
+ .combine('storeOperation1', kStoreOps)
+ .combine('storeOperation2', kStoreOps)
+ .beginSubcases()
+ .combine('colorAttachments', kNumColorAttachments)
+ )
+ .fn(t => {
+ const kColorFormat = 'rgba8unorm';
+ const colorAttachments = [];
+
+ for (let i = 0; i < t.params.colorAttachments; i++) {
+ colorAttachments.push(
+ t.device.createTexture({
+ format: kColorFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ );
+ }
+
+ // Color load operation will clear to {1.0, 1.0, 1.0, 1.0}
+ // Color store operation is determined by test params. Use storeOperation1 for even numbered
+ // attachments and storeOperation2 for odd numbered attachments.
+ const renderPassColorAttachments = [];
+ for (let i = 0; i < t.params.colorAttachments; i++) {
+ renderPassColorAttachments.push({
+ view: colorAttachments[i].createView(),
+ clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: i % 2 === 0 ? t.params.storeOperation1 : t.params.storeOperation2,
+ });
+ }
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: renderPassColorAttachments,
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // Check that the correct store operation occurred.
+ let expectedValue = {};
+ for (let i = 0; i < t.params.colorAttachments; i++) {
+ if (renderPassColorAttachments[i].storeOp === 'discard') {
+ // If colorStoreOp was clear, the texture should now contain {0.0, 0.0, 0.0, 0.0}.
+ expectedValue = { R: 0.0, G: 0.0, B: 0.0, A: 0.0 };
+ } else if (renderPassColorAttachments[i].storeOp === 'store') {
+ // If colorStoreOP was store, the texture should still contain {1.0, 1.0, 1.0, 1.0}.
+ expectedValue = { R: 1.0, G: 1.0, B: 1.0, A: 1.0 };
+ }
+ t.expectSingleColor(colorAttachments[i], kColorFormat, {
+ size: [kHeight, kWidth, 1],
+ exp: expectedValue,
+ });
+ }
+ });
+
+g.test('render_pass_store_op,depth_stencil_attachment_only')
+ .desc(
+ `
+Tests that render pass depth stencil store operations work correctly for all renderable color
+formats, mip levels and array layers.
+
+- x= all (sized) depth stencil formats, all store ops, multiple mip levels, multiple array layers
+
+TODO: Also test unsized depth/stencil formats [1]
+ `
+ )
+ .params(u =>
+ u
+ .combine('depthStencilFormat', kSizedDepthStencilFormats) // [1]
+ .combine('storeOperation', kStoreOps)
+ .beginSubcases()
+ .combine('mipLevel', kMipLevel)
+ .combine('arrayLayer', kArrayLayers)
+ )
+ .fn(t => {
+ const depthStencilTexture = t.device.createTexture({
+ format: t.params.depthStencilFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: t.params.arrayLayer + 1 },
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const depthStencilViewDesc = {
+ baseArrayLayer: t.params.arrayLayer,
+ baseMipLevel: t.params.mipLevel,
+ mipLevelCount: 1,
+ arrayLayerCount: 1,
+ };
+
+ const depthStencilAttachmentView = depthStencilTexture.createView(depthStencilViewDesc);
+
+ // Depth-stencil load operation will clear to depth = 1.0, stencil = 1.0.
+ // Depth-stencil store operate is determined by test params.
+ const encoder = t.device.createCommandEncoder();
+ const depthStencilAttachment = {
+ view: depthStencilAttachmentView,
+ };
+ if (kTextureFormatInfo[t.params.depthStencilFormat].depth) {
+ depthStencilAttachment.depthClearValue = 1.0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = t.params.storeOperation;
+ }
+ if (kTextureFormatInfo[t.params.depthStencilFormat].stencil) {
+ depthStencilAttachment.stencilClearValue = 1;
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = t.params.storeOperation;
+ }
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment,
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ let expectedDepthValue = {};
+ let expectedStencilValue = {};
+ if (t.params.storeOperation === 'discard') {
+ // If depthStencilStoreOperation was clear, the texture's depth/stencil component should be 0,
+ expectedDepthValue = { Depth: 0.0 };
+ expectedStencilValue = { Stencil: 0 };
+ } else if (t.params.storeOperation === 'store') {
+ // If depthStencilStoreOperation was store, the texture's depth/stencil components should be 1,
+ expectedDepthValue = { Depth: 1.0 };
+ expectedStencilValue = { Stencil: 1 };
+ }
+
+ if (kTextureFormatInfo[t.params.depthStencilFormat].depth) {
+ t.expectSingleColor(depthStencilTexture, t.params.depthStencilFormat, {
+ size: [kHeight, kWidth, 1],
+ slice: t.params.arrayLayer,
+ exp: expectedDepthValue,
+ layout: { mipLevel: t.params.mipLevel, aspect: 'depth-only' },
+ });
+ }
+ if (kTextureFormatInfo[t.params.depthStencilFormat].stencil) {
+ t.expectSingleColor(depthStencilTexture, t.params.depthStencilFormat, {
+ size: [kHeight, kWidth, 1],
+ slice: t.params.arrayLayer,
+ exp: expectedStencilValue,
+ layout: { mipLevel: t.params.mipLevel, aspect: 'stencil-only' },
+ });
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeop2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeop2.spec.js
new file mode 100644
index 0000000000..9fe3fa7437
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pass/storeop2.spec.js
@@ -0,0 +1,84 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+renderPass store op test that drawn quad is either stored or cleared based on storeop
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('storeOp_controls_whether_1x1_drawn_quad_is_stored')
+ .desc(
+ `
+TODO: is this duplicated with api,operation,render_pass,storeOp?
+TODO: needs review and rename
+`
+ )
+ .paramsSimple([
+ { storeOp: 'store', _expected: 1 }, //
+ { storeOp: 'discard', _expected: 0 },
+ ])
+ .fn(async t => {
+ const renderTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'r8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ // create render pipeline
+ const renderPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'r8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ // encode pass and submit
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTexture.createView(),
+ storeOp: t.params.storeOp,
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(renderPipeline);
+ pass.draw(3);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // expect the buffer to be clear
+ t.expectSingleColor(renderTexture, 'r8unorm', {
+ size: [1, 1, 1],
+ exp: { R: t.params._expected },
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/alpha_to_coverage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/alpha_to_coverage.spec.js
new file mode 100644
index 0000000000..cd2584c989
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/alpha_to_coverage.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- for sampleCount = 4, alphaToCoverageEnabled = true and various combinations of:
+ - rasterization masks
+ - increasing alpha values of the first color output including { < 0, = 0, = 1/16, = 2/16, ..., = 15/16, = 1, > 1 }
+ - alpha values of the second color output = { 0, 0.5, 1.0 }.
+- test that for a single pixel in { first, second } { color, depth, stencil } output the final sample mask is applied to it, moreover:
+ - if alpha is 0.0 or less then alpha to coverage mask is 0x0,
+ - if alpha is 1.0 or greater then alpha to coverage mask is 0xFFFFFFFF,
+ - that the number of bits in the alpha to coverage mask is non-decreasing,
+ - that the computation of alpha to coverage mask doesn't depend on any other color output than first,
+ - (not included in the spec): that once a sample is included in the alpha to coverage sample mask
+ it will be included for any alpha greater than or equal to the current value.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/culling_tests.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/culling_tests.spec.js
new file mode 100644
index 0000000000..f2d0df1e95
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/culling_tests.spec.js
@@ -0,0 +1,186 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Test culling and rasterization state.
+
+Test coverage:
+Test all culling combinations of GPUFrontFace and GPUCullMode show the correct output.
+
+Use 2 triangles with different winding orders:
+
+- Test that the counter-clock wise triangle has correct output for:
+ - All FrontFaces (ccw, cw)
+ - All CullModes (none, front, back)
+ - All depth stencil attachment types (none, depth24plus, depth32float, depth24plus-stencil8)
+ - Some primitive topologies (triangle-list, TODO: triangle-strip)
+
+- Test that the clock wise triangle has correct output for:
+ - All FrontFaces (ccw, cw)
+ - All CullModes (none, front, back)
+ - All depth stencil attachment types (none, depth24plus, depth32float, depth24plus-stencil8)
+ - Some primitive topologies (triangle-list, TODO: triangle-strip)
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kTextureFormatInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+function faceIsCulled(face, frontFace, cullMode) {
+ return cullMode !== 'none' && (frontFace === face) === (cullMode === 'front');
+}
+
+function faceColor(face, frontFace, cullMode) {
+ // front facing color is green, non front facing is red, background is blue
+ const isCulled = faceIsCulled(face, frontFace, cullMode);
+ if (!isCulled && face === frontFace) {
+ return new Uint8Array([0x00, 0xff, 0x00, 0xff]);
+ } else if (isCulled) {
+ return new Uint8Array([0x00, 0x00, 0xff, 0xff]);
+ } else {
+ return new Uint8Array([0xff, 0x00, 0x00, 0xff]);
+ }
+}
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('culling')
+ .desc(
+ `
+TODO: test triangle-strip as well [1]
+TODO: check the contents of the depth and stencil outputs [2]
+`
+ )
+ .params(
+ u =>
+ u
+ .combine('frontFace', ['ccw', 'cw'])
+ .combine('cullMode', ['none', 'front', 'back'])
+ .beginSubcases()
+ .combine('depthStencilFormat', [
+ null,
+ 'depth24plus',
+ 'depth32float',
+ 'depth24plus-stencil8',
+ ])
+ .combine('primitiveTopology', ['triangle-list']) // [1]
+ )
+ .fn(t => {
+ const size = 4;
+ const format = 'rgba8unorm';
+
+ const texture = t.device.createTexture({
+ size: { width: size, height: size, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+
+ let depthTexture = undefined;
+ let depthStencilAttachment = undefined;
+ if (t.params.depthStencilFormat) {
+ depthTexture = t.device.createTexture({
+ size: { width: size, height: size, depthOrArrayLayers: 1 },
+ format: t.params.depthStencilFormat,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ depthStencilAttachment = {
+ view: depthTexture.createView(),
+ depthClearValue: 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ };
+
+ if (t.params.depthStencilFormat && kTextureFormatInfo[t.params.depthStencilFormat].stencil) {
+ depthStencilAttachment.stencilClearValue = 0;
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+ }
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: texture.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 1.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+
+ // Draw two triangles with different winding orders:
+ // 1. The top-left one is counterclockwise (CCW)
+ // 2. The bottom-right one is clockwise (CW)
+ pass.setPipeline(
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, 0.0),
+ vec2<f32>( 0.0, 1.0),
+ vec2<f32>( 0.0, -1.0),
+ vec2<f32>( 1.0, 0.0),
+ vec2<f32>( 1.0, -1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main(
+ @builtin(front_facing) FrontFacing : bool
+ ) -> @location(0) vec4<f32> {
+ var color : vec4<f32>;
+ if (FrontFacing) {
+ color = vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ } else {
+ color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ return color;
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: {
+ topology: t.params.primitiveTopology,
+ frontFace: t.params.frontFace,
+ cullMode: t.params.cullMode,
+ },
+ depthStencil: depthTexture ? { format: t.params.depthStencilFormat } : undefined,
+ })
+ );
+
+ pass.draw(6, 1, 0, 0);
+ pass.end();
+
+ t.device.queue.submit([encoder.finish()]);
+
+ // front facing color is green, non front facing is red, background is blue
+ const kCCWTriangleTopLeftColor = faceColor('ccw', t.params.frontFace, t.params.cullMode);
+ t.expectSinglePixelIn2DTexture(
+ texture,
+ format,
+ { x: 0, y: 0 },
+ { exp: kCCWTriangleTopLeftColor }
+ );
+
+ const kCWTriangleBottomRightColor = faceColor('cw', t.params.frontFace, t.params.cullMode);
+ t.expectSinglePixelIn2DTexture(
+ texture,
+ format,
+ { x: size - 1, y: size - 1 },
+ { exp: kCWTriangleBottomRightColor }
+ );
+
+ // [2]: check the contents of the depth and stencil outputs
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/overrides.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/overrides.spec.js
new file mode 100644
index 0000000000..dcc76eb8d0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/overrides.spec.js
@@ -0,0 +1,424 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Testing render pipeline using overridable constants in vertex stage and fragment stage.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+class F extends GPUTest {
+ async ExpectShaderOutputWithConstants(isAsync, format, expected, vertex, fragment) {
+ const renderTarget = this.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const descriptor = {
+ layout: 'auto',
+ vertex,
+ fragment,
+ primitive: {
+ topology: 'triangle-list',
+ frontFace: 'ccw',
+ cullMode: 'back',
+ },
+ };
+
+ const promise = isAsync
+ ? this.device.createRenderPipelineAsync(descriptor)
+ : Promise.resolve(this.device.createRenderPipeline(descriptor));
+
+ const pipeline = await promise;
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ clearValue: {
+ r: kClearValueResult.R,
+ g: kClearValueResult.G,
+ b: kClearValueResult.B,
+ a: kClearValueResult.A,
+ },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ this.expectSingleColor(renderTarget, format, {
+ size: [1, 1, 1],
+ exp: expected,
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kClearValueResult = { R: 0.2, G: 0.4, B: 0.6, A: 0.8 };
+const kDefaultValueResult = { R: 1.0, G: 1.0, B: 1.0, A: 1.0 };
+
+const kFullScreenTriangleVertexShader = `
+override xright: f32 = 3.0;
+override ytop: f32 = 3.0;
+
+@vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, ytop),
+ vec2<f32>(-1.0, -ytop),
+ vec2<f32>(xright, 0.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+}
+`;
+
+const kFullScreenTriangleFragmentShader = `
+override R: f32 = 1.0;
+override G: f32 = 1.0;
+override B: f32 = 1.0;
+override A: f32 = 1.0;
+
+@fragment fn main()
+ -> @location(0) vec4<f32> {
+ return vec4<f32>(R, G, B, A);
+}
+`;
+
+g.test('basic')
+ .desc(
+ `Test that either correct constants override values or default values when no constants override value are provided at pipeline creation time are used correctly in vertex and fragment shader.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [true, false])
+ .beginSubcases()
+ .combineWithParams([
+ {
+ expected: kDefaultValueResult,
+ vertexConstants: {},
+ fragmentConstants: {},
+ },
+ {
+ expected: kClearValueResult,
+ vertexConstants: {
+ xright: -3.0,
+ },
+ fragmentConstants: {},
+ },
+ {
+ expected: kClearValueResult,
+ vertexConstants: {
+ ytop: -3.0,
+ },
+ fragmentConstants: {},
+ },
+ {
+ expected: kDefaultValueResult,
+ vertexConstants: {
+ xright: 4.0,
+ ytop: 4.0,
+ },
+ fragmentConstants: {},
+ },
+ {
+ expected: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ vertexConstants: {},
+ fragmentConstants: { R: 0.0, B: 0.0 },
+ },
+ {
+ expected: { R: 0.0, G: 0.0, B: 0.0, A: 0.0 },
+ vertexConstants: {},
+ fragmentConstants: { R: 0.0, G: 0.0, B: 0.0, A: 0.0 },
+ },
+ ])
+ )
+ .fn(async t => {
+ const format = 'bgra8unorm';
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ format,
+ t.params.expected,
+ {
+ module: t.device.createShaderModule({
+ code: kFullScreenTriangleVertexShader,
+ }),
+ entryPoint: 'main',
+ constants: t.params.vertexConstants,
+ },
+ {
+ module: t.device.createShaderModule({
+ code: kFullScreenTriangleFragmentShader,
+ }),
+ entryPoint: 'main',
+ constants: t.params.fragmentConstants,
+ targets: [{ format }],
+ }
+ );
+ });
+
+g.test('precision')
+ .desc(`Test that the float number precision is preserved for constants`)
+ .params(u =>
+ u
+ .combine('isAsync', [true, false])
+ .beginSubcases()
+ .combineWithParams([
+ {
+ expected: { R: 3.14159, G: 1.0, B: 1.0, A: 1.0 },
+ vertexConstants: {},
+ fragmentConstants: { R: 3.14159 },
+ },
+ {
+ expected: { R: 3.141592653589793238, G: 1.0, B: 1.0, A: 1.0 },
+ vertexConstants: {},
+ fragmentConstants: { R: 3.141592653589793238 },
+ },
+ ])
+ )
+ .fn(async t => {
+ const format = 'rgba32float';
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ format,
+ t.params.expected,
+ {
+ module: t.device.createShaderModule({
+ code: kFullScreenTriangleVertexShader,
+ }),
+ entryPoint: 'main',
+ constants: t.params.vertexConstants,
+ },
+ {
+ module: t.device.createShaderModule({
+ code: kFullScreenTriangleFragmentShader,
+ }),
+ entryPoint: 'main',
+ constants: t.params.fragmentConstants,
+ targets: [{ format }],
+ }
+ );
+ });
+
+g.test('shared_shader_module')
+ .desc(
+ `Test that when the same module is shared by different pipelines, the constant values are still being used correctly.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [true, false])
+ .beginSubcases()
+ .combineWithParams([
+ {
+ expected0: kClearValueResult,
+ vertexConstants0: {
+ xright: -3.0,
+ },
+ fragmentConstants0: {},
+
+ expected1: kDefaultValueResult,
+ vertexConstants1: {},
+ fragmentConstants1: {},
+ },
+ {
+ expected0: { R: 0.0, G: 0.0, B: 0.0, A: 0.0 },
+ vertexConstants0: {},
+ fragmentConstants0: { R: 0.0, G: 0.0, B: 0.0, A: 0.0 },
+
+ expected1: kDefaultValueResult,
+ vertexConstants1: {},
+ fragmentConstants1: {},
+ },
+ {
+ expected0: { R: 1.0, G: 0.0, B: 1.0, A: 0.0 },
+ vertexConstants0: {},
+ fragmentConstants0: { R: 1.0, G: 0.0, B: 1.0, A: 0.0 },
+
+ expected1: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ vertexConstants1: {},
+ fragmentConstants1: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ },
+ ])
+ )
+ .fn(async t => {
+ const format = 'bgra8unorm';
+ const vertexModule = t.device.createShaderModule({
+ code: kFullScreenTriangleVertexShader,
+ });
+
+ const fragmentModule = t.device.createShaderModule({
+ code: kFullScreenTriangleFragmentShader,
+ });
+
+ const createPipelineFn = async (vertexConstants, fragmentConstants) => {
+ const descriptor = {
+ layout: 'auto',
+ vertex: {
+ module: vertexModule,
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: fragmentModule,
+ entryPoint: 'main',
+ targets: [{ format }],
+ constants: fragmentConstants,
+ },
+ primitive: {
+ topology: 'triangle-list',
+ frontFace: 'ccw',
+ cullMode: 'back',
+ },
+ };
+
+ return t.params.isAsync
+ ? t.device.createRenderPipelineAsync(descriptor)
+ : t.device.createRenderPipeline(descriptor);
+ };
+
+ const pipeline0 = await createPipelineFn(
+ t.params.vertexConstants0,
+ t.params.fragmentConstants0
+ );
+
+ const pipeline1 = await createPipelineFn(
+ t.params.vertexConstants1,
+ t.params.fragmentConstants1
+ );
+
+ const renderTarget0 = t.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const renderTarget1 = t.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+
+ const pass0 = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget0.createView(),
+ storeOp: 'store',
+ clearValue: {
+ r: kClearValueResult.R,
+ g: kClearValueResult.G,
+ b: kClearValueResult.B,
+ a: kClearValueResult.A,
+ },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass0.setPipeline(pipeline0);
+ pass0.draw(3);
+ pass0.end();
+
+ const pass1 = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget1.createView(),
+ storeOp: 'store',
+ clearValue: {
+ r: kClearValueResult.R,
+ g: kClearValueResult.G,
+ b: kClearValueResult.B,
+ a: kClearValueResult.A,
+ },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass1.setPipeline(pipeline1);
+ pass1.draw(3);
+ pass1.end();
+
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectSingleColor(renderTarget0, format, {
+ size: [1, 1, 1],
+ exp: t.params.expected0,
+ });
+ t.expectSingleColor(renderTarget1, format, {
+ size: [1, 1, 1],
+ exp: t.params.expected1,
+ });
+ });
+
+g.test('multi_entry_points')
+ .desc(
+ `Test that when the same module is shared by vertex and fragment shader, the constant values are still being used correctly.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [true, false])
+ .beginSubcases()
+ .combineWithParams([
+ {
+ expected: { R: 0.8, G: 0.4, B: 0.2, A: 1.0 },
+ vertexConstants: { A: 4.0, B: 4.0 },
+ fragmentConstants: { A: 0.8, B: 0.4, C: 0.2, D: 1.0 },
+ },
+ {
+ expected: { R: 0.8, G: 0.4, B: 0.2, A: 1.0 },
+ vertexConstants: {},
+ fragmentConstants: { A: 0.8, B: 0.4, C: 0.2, D: 1.0 },
+ },
+ {
+ expected: kClearValueResult,
+ vertexConstants: { A: -3.0 },
+ fragmentConstants: { A: 0.8, B: 0.4, C: 0.2, D: 1.0 },
+ },
+ ])
+ )
+ .fn(async t => {
+ const format = 'bgra8unorm';
+ const module = t.device.createShaderModule({
+ code: `
+ override A: f32 = 3.0;
+ override B: f32 = 3.0;
+ override C: f32;
+ override D: f32;
+
+ @vertex fn vertexMain(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, A),
+ vec2<f32>(-1.0, -A),
+ vec2<f32>(B, 0.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+
+ @fragment fn fragmentMain()
+ -> @location(0) vec4<f32> {
+ return vec4<f32>(A, B, C, D);
+ }
+ `,
+ });
+ await t.ExpectShaderOutputWithConstants(
+ t.params.isAsync,
+ format,
+ t.params.expected,
+ {
+ module,
+ entryPoint: 'vertexMain',
+ constants: t.params.vertexConstants,
+ },
+ {
+ module,
+ entryPoint: 'fragmentMain',
+ constants: t.params.fragmentConstants,
+ targets: [{ format }],
+ }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.js
new file mode 100644
index 0000000000..27ec3915f0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.js
@@ -0,0 +1,462 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+- Test pipeline outputs with different color attachment number, formats, component counts, etc.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import {
+ kLimitInfo,
+ kRenderableColorTextureFormats,
+ kTextureFormatInfo,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { getFragmentShaderCodeWithOutput, getPlainTypeInfo } from '../../../util/shader.js';
+import { kTexelRepresentationInfo } from '../../../util/texture/texel_data.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+
+const kVertexShader = `
+@vertex fn main(
+@builtin(vertex_index) VertexIndex : u32
+) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, -3.0),
+ vec2<f32>(3.0, 1.0),
+ vec2<f32>(-1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+}
+`;
+
+export const g = makeTestGroup(GPUTest);
+
+// Values to write into each attachment
+// We make values different for each attachment index and each channel
+// to make sure they didn't get mixed up
+const attachmentsIntWriteValues = [
+ { R: 1, G: 2, B: 3, A: 4 },
+ { R: 5, G: 6, B: 7, A: 8 },
+ { R: 9, G: 10, B: 11, A: 12 },
+ { R: 13, G: 14, B: 15, A: 16 },
+];
+
+const attachmentsFloatWriteValues = [
+ { R: 0.12, G: 0.34, B: 0.56, A: 0 },
+ { R: 0.78, G: 0.9, B: 0.19, A: 1 },
+ { R: 0.28, G: 0.37, B: 0.46, A: 0.3 },
+ { R: 0.55, G: 0.64, B: 0.73, A: 1 },
+];
+
+g.test('color,attachments')
+ .desc(`Test that pipeline with sparse color attachments write values correctly.`)
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine('attachmentCount', [2, 3, 4])
+ .filter(t => {
+ // We only need to test formats that have a valid color attachment bytes per sample.
+ const pixelByteCost = kTextureFormatInfo[t.format].renderTargetPixelByteCost;
+ return (
+ pixelByteCost !== undefined &&
+ pixelByteCost * t.attachmentCount <= kLimitInfo.maxColorAttachmentBytesPerSample.default
+ );
+ })
+ .expand('emptyAttachmentId', p => range(p.attachmentCount, i => i))
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, attachmentCount, emptyAttachmentId } = t.params;
+ const componentCount = kTexelRepresentationInfo[format].componentOrder.length;
+ const info = kTextureFormatInfo[format];
+
+ const writeValues =
+ info.sampleType === 'sint' || info.sampleType === 'uint'
+ ? attachmentsIntWriteValues
+ : attachmentsFloatWriteValues;
+
+ const renderTargets = range(attachmentCount, () =>
+ t.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ );
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kVertexShader,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: getFragmentShaderCodeWithOutput(
+ range(attachmentCount, i =>
+ i === emptyAttachmentId
+ ? null
+ : {
+ values: [
+ writeValues[i].R,
+ writeValues[i].G,
+ writeValues[i].B,
+ writeValues[i].A,
+ ],
+
+ plainType: getPlainTypeInfo(info.sampleType),
+ componentCount,
+ }
+ )
+ ),
+ }),
+ entryPoint: 'main',
+ targets: range(attachmentCount, i => (i === emptyAttachmentId ? null : { format })),
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: range(attachmentCount, i =>
+ i === emptyAttachmentId
+ ? null
+ : {
+ view: renderTargets[i].createView(),
+ storeOp: 'store',
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 0.5 },
+ loadOp: 'clear',
+ }
+ ),
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ const promises = range(attachmentCount, i => {
+ if (i === emptyAttachmentId) {
+ return undefined;
+ }
+ return textureContentIsOKByT2B(
+ t,
+ { texture: renderTargets[i] },
+ [1, 1, 1],
+ {
+ expTexelView: TexelView.fromTexelsAsColors(format, coords => writeValues[i]),
+ },
+ {
+ maxIntDiff: 0,
+ maxDiffULPsForNormFormat: 1,
+ maxDiffULPsForFloatFormat: 1,
+ }
+ );
+ });
+ t.eventualExpectOK(Promise.all(promises));
+ });
+
+g.test('color,component_count')
+ .desc(
+ `Test that extra components of the output (e.g. f32, vec2<f32>, vec3<f32>, vec4<f32>) are discarded.`
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine('componentCount', [1, 2, 3, 4])
+ .filter(x => x.componentCount >= kTexelRepresentationInfo[x.format].componentOrder.length)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, componentCount } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ // expected RGBA values
+ // extra channels are discarded
+ const values = [0, 1, 0, 1];
+
+ const renderTarget = t.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kVertexShader,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: getFragmentShaderCodeWithOutput([
+ {
+ values,
+ plainType: getPlainTypeInfo(info.sampleType),
+ componentCount,
+ },
+ ]),
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectSingleColor(renderTarget, format, {
+ size: [1, 1, 1],
+ exp: { R: values[0], G: values[1], B: values[2], A: values[3] },
+ });
+ });
+
+g.test('color,component_count,blend')
+ .desc(
+ `Test that blending behaves correctly when:
+- fragment output has no alpha, but the src alpha is not used for the blend operation indicated by blend factors
+- attachment format has no alpha, and the dst alpha should be assumed as 1
+
+The attachment has a load value of [1, 0, 0, 1]
+`
+ )
+ .params(u =>
+ u
+ .combine('format', ['r8unorm', 'rg8unorm', 'rgba8unorm', 'bgra8unorm'])
+ .beginSubcases()
+ // _result is expected values in the color attachment (extra channels are discarded)
+ // output is the fragment shader output vector
+ // 0.498 -> 0x7f, 0.502 -> 0x80
+ .combineWithParams([
+ // fragment output has no alpha
+ {
+ _result: [0, 0, 0, 0],
+ output: [0],
+ colorSrcFactor: 'one',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0, 0, 0, 0],
+ output: [0],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [1, 0, 0, 0],
+ output: [0],
+ colorSrcFactor: 'one-minus-dst-alpha',
+ colorDstFactor: 'dst-alpha',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'one',
+ },
+ {
+ _result: [0.498, 0, 0, 0],
+ output: [0.498],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'one',
+ },
+ {
+ _result: [0, 1, 0, 0],
+ output: [0, 1],
+ colorSrcFactor: 'one',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0, 1, 0, 0],
+ output: [0, 1],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [1, 0, 0, 0],
+ output: [0, 1],
+ colorSrcFactor: 'one-minus-dst-alpha',
+ colorDstFactor: 'dst-alpha',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'one',
+ },
+ {
+ _result: [0, 1, 0, 0],
+ output: [0, 1, 0],
+ colorSrcFactor: 'one',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0, 1, 0, 0],
+ output: [0, 1, 0],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [1, 0, 0, 0],
+ output: [0, 1, 0],
+ colorSrcFactor: 'one-minus-dst-alpha',
+ colorDstFactor: 'dst-alpha',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'one',
+ },
+ // fragment output has alpha
+ {
+ _result: [0.502, 1, 0, 0.498],
+ output: [0, 1, 0, 0.498],
+ colorSrcFactor: 'one',
+ colorDstFactor: 'one-minus-src-alpha',
+ alphaSrcFactor: 'one',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0.502, 0.498, 0, 0.498],
+ output: [0, 1, 0, 0.498],
+ colorSrcFactor: 'src-alpha',
+ colorDstFactor: 'one-minus-src-alpha',
+ alphaSrcFactor: 'one',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0, 1, 0, 0.498],
+ output: [0, 1, 0, 0.498],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'one',
+ alphaDstFactor: 'zero',
+ },
+ {
+ _result: [0, 1, 0, 0.498],
+ output: [0, 1, 0, 0.498],
+ colorSrcFactor: 'dst-alpha',
+ colorDstFactor: 'zero',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'src',
+ },
+ {
+ _result: [1, 0, 0, 1],
+ output: [0, 1, 0, 0.498],
+ colorSrcFactor: 'one-minus-dst-alpha',
+ colorDstFactor: 'dst-alpha',
+ alphaSrcFactor: 'zero',
+ alphaDstFactor: 'dst-alpha',
+ },
+ ])
+ .filter(x => x.output.length >= kTexelRepresentationInfo[x.format].componentOrder.length)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ format,
+ _result,
+ output,
+ colorSrcFactor,
+ colorDstFactor,
+ alphaSrcFactor,
+ alphaDstFactor,
+ } = t.params;
+ const componentCount = output.length;
+ const info = kTextureFormatInfo[format];
+
+ const renderTarget = t.device.createTexture({
+ format,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kVertexShader,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: getFragmentShaderCodeWithOutput([
+ {
+ values: output,
+ plainType: getPlainTypeInfo(info.sampleType),
+ componentCount,
+ },
+ ]),
+ }),
+ entryPoint: 'main',
+ targets: [
+ {
+ format,
+ blend: {
+ color: {
+ srcFactor: colorSrcFactor,
+ dstFactor: colorDstFactor,
+ operation: 'add',
+ },
+ alpha: {
+ srcFactor: alphaSrcFactor,
+ dstFactor: alphaDstFactor,
+ operation: 'add',
+ },
+ },
+ },
+ ],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectSingleColor(renderTarget, format, {
+ size: [1, 1, 1],
+ exp: { R: _result[0], G: _result[1], B: _result[2], A: _result[3] },
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/primitive_topology.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/primitive_topology.spec.js
new file mode 100644
index 0000000000..d718adeb0c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/primitive_topology.spec.js
@@ -0,0 +1,482 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Test primitive topology rendering.
+
+Draw a primitive using 6 vertices with each topology and check if the pixel is covered.
+
+Vertex sequence and coordinates are the same for each topology:
+ - Vertex buffer = [v1, v2, v3, v4, v5, v6]
+ - Topology = [point-list, line-list, line-strip, triangle-list, triangle-strip]
+
+Test locations are framebuffer coordinates:
+ - Pixel value { valid: green, invalid: black, format: 'rgba8unorm'}
+ - Test point is valid if the pixel value equals the covered pixel value at the test location.
+ - Primitive restart occurs for strips (line-strip and triangle-strip) between [v3, v4].
+
+ Topology: point-list Valid test location(s) Invalid test location(s)
+
+ v2 v4 v6 Every vertex. Line-strip locations.
+ Triangle-list locations.
+ Triangle-strip locations.
+
+ v1 v3 v5
+
+ Topology: line-list (3 lines)
+
+ v2 v4 v6 Center of three line segments: Line-strip locations.
+ * * * {v1,V2}, {v3,v4}, and {v4,v5}. Triangle-list locations.
+ * * * Triangle-strip locations.
+ * * *
+ v1 v3 v5
+
+ Topology: line-strip (5 lines)
+
+ v2 v4 v6
+ ** ** *
+ * * * * * Line-list locations Triangle-list locations.
+ * ** ** + Center of two line segments: Triangle-strip locations.
+ v1 v3 v5 {v2,v3} and {v4,v5}.
+ With primitive restart:
+ Line segment {v3, v4}.
+
+ Topology: triangle-list (2 triangles)
+
+ v2 v4 v6
+ ** ****** Center of two triangle(s): Triangle-strip locations.
+ **** **** {v1,v2,v3} and {v4,v5,v6}.
+ ****** **
+ v1 v3 v5
+
+ Topology: triangle-strip (4 triangles)
+
+ v2 v4 v6
+ ** ****** ** ****** Triangle-list locations None.
+ **** **** **** **** + Center of two triangle(s):
+ ****** ** ****** ** {v2,v3,v4} and {v3,v4,v5}. With primitive restart:
+ v1 v3 v5 Triangle {v2, v3, v4}
+ and {v3, v4, v5}.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+const kRTSize = 56;
+const kColorFormat = 'rgba8unorm';
+const kValidPixelColor = new Uint8Array([0x00, 0xff, 0x00, 0xff]); // green
+const kInvalidPixelColor = new Uint8Array([0x00, 0x00, 0x00, 0x00]); // black
+
+class Point2D {
+ constructor(x, y) {
+ this.x = x;
+ this.y = y;
+ this.z = 0;
+ this.w = 1;
+ }
+
+ toNDC() {
+ // NDC coordinate space is y-up, so we negate the y mapping.
+ // To ensure the resulting vertex in NDC will be placed at the center of the pixel, we
+ // must offset by the pixel coordinates or 0.5.
+ return new Point2D((2 * (this.x + 0.5)) / kRTSize - 1, (-2 * (this.y + 0.5)) / kRTSize + 1);
+ }
+
+ static getMidpoint(a, b) {
+ return new Point2D((a.x + b.x) / 2, (a.y + b.y) / 2);
+ }
+
+ static getCentroid(a, b, c) {
+ return new Point2D((a.x + b.x + c.x) / 3, (a.y + b.y + c.y) / 3);
+ }
+}
+
+const VertexLocations = [
+ new Point2D(8, 24), // v1
+ new Point2D(16, 8), // v2
+ new Point2D(24, 24), // v3
+ new Point2D(32, 8), // v4
+ new Point2D(40, 24), // v5
+ new Point2D(48, 8), // v6
+];
+
+function getPointTestLocations(expectedColor) {
+ // Test points are always equal to vertex locations.
+ const testLocations = [];
+ for (const location of VertexLocations) {
+ testLocations.push({ location, color: expectedColor });
+ }
+ return testLocations;
+}
+
+function getLineTestLocations(expectedColor) {
+ // Midpoints of 3 line segments
+ return [
+ {
+ // Line {v1, v2}
+ location: Point2D.getMidpoint(VertexLocations[0], VertexLocations[1]),
+ color: expectedColor,
+ },
+ {
+ // Line {v3, v4}
+ location: Point2D.getMidpoint(VertexLocations[2], VertexLocations[3]),
+ color: expectedColor,
+ },
+ {
+ // Line {v5, v6}
+ location: Point2D.getMidpoint(VertexLocations[4], VertexLocations[5]),
+ color: expectedColor,
+ },
+ ];
+}
+
+function getPrimitiveRestartLineTestLocations(expectedColor) {
+ // Midpoints of 2 line segments
+ return [
+ {
+ // Line {v1, v2}
+ location: Point2D.getMidpoint(VertexLocations[0], VertexLocations[1]),
+ color: expectedColor,
+ },
+ {
+ // Line {v5, v6}
+ location: Point2D.getMidpoint(VertexLocations[4], VertexLocations[5]),
+ color: expectedColor,
+ },
+ ];
+}
+
+function getLineStripTestLocations(expectedColor) {
+ // Midpoints of 2 line segments
+ return [
+ {
+ // Line {v2, v3}
+ location: Point2D.getMidpoint(VertexLocations[1], VertexLocations[2]),
+ color: expectedColor,
+ },
+ {
+ // Line {v4, v5}
+ location: Point2D.getMidpoint(VertexLocations[3], VertexLocations[4]),
+ color: expectedColor,
+ },
+ ];
+}
+
+function getTriangleListTestLocations(expectedColor) {
+ // Center of two triangles
+ return [
+ {
+ // Triangle {v1, v2, v3}
+ location: Point2D.getCentroid(VertexLocations[0], VertexLocations[1], VertexLocations[2]),
+ color: expectedColor,
+ },
+ {
+ // Triangle {v4, v5, v6}
+ location: Point2D.getCentroid(VertexLocations[3], VertexLocations[4], VertexLocations[5]),
+ color: expectedColor,
+ },
+ ];
+}
+
+function getTriangleStripTestLocations(expectedColor) {
+ // Center of two triangles
+ return [
+ {
+ // Triangle {v2, v3, v4}
+ location: Point2D.getCentroid(VertexLocations[1], VertexLocations[2], VertexLocations[3]),
+ color: expectedColor,
+ },
+ {
+ // Triangle {v3, v4, v5}
+ location: Point2D.getCentroid(VertexLocations[2], VertexLocations[3], VertexLocations[4]),
+ color: expectedColor,
+ },
+ ];
+}
+
+function getDefaultTestLocations({
+ topology,
+ primitiveRestart = false,
+ invalidateLastInList = false,
+}) {
+ function maybeInvalidateLast(locations) {
+ if (!invalidateLastInList) return locations;
+
+ return locations.map((tl, i) => {
+ if (i === locations.length - 1) {
+ return {
+ location: tl.location,
+ color: kInvalidPixelColor,
+ };
+ } else {
+ return tl;
+ }
+ });
+ }
+
+ let testLocations;
+ switch (topology) {
+ case 'point-list':
+ testLocations = [
+ ...getPointTestLocations(kValidPixelColor),
+ ...getLineStripTestLocations(kInvalidPixelColor),
+ ...getTriangleListTestLocations(kInvalidPixelColor),
+ ...getTriangleStripTestLocations(kInvalidPixelColor),
+ ];
+
+ break;
+ case 'line-list':
+ testLocations = [
+ ...maybeInvalidateLast(getLineTestLocations(kValidPixelColor)),
+ ...getLineStripTestLocations(kInvalidPixelColor),
+ ...getTriangleListTestLocations(kInvalidPixelColor),
+ ...getTriangleStripTestLocations(kInvalidPixelColor),
+ ];
+
+ break;
+ case 'line-strip':
+ testLocations = [
+ ...(primitiveRestart
+ ? getPrimitiveRestartLineTestLocations(kValidPixelColor)
+ : getLineTestLocations(kValidPixelColor)),
+ ...getLineStripTestLocations(kValidPixelColor),
+ ...getTriangleListTestLocations(kInvalidPixelColor),
+ ...getTriangleStripTestLocations(kInvalidPixelColor),
+ ];
+
+ break;
+ case 'triangle-list':
+ testLocations = [
+ ...maybeInvalidateLast(getTriangleListTestLocations(kValidPixelColor)),
+ ...getTriangleStripTestLocations(kInvalidPixelColor),
+ ];
+
+ break;
+ case 'triangle-strip':
+ testLocations = [
+ ...getTriangleListTestLocations(kValidPixelColor),
+ ...getTriangleStripTestLocations(primitiveRestart ? kInvalidPixelColor : kValidPixelColor),
+ ];
+
+ break;
+ }
+
+ return testLocations;
+}
+
+function generateVertexBuffer(vertexLocations) {
+ const vertexCoords = new Float32Array(vertexLocations.length * 4);
+ for (let i = 0; i < vertexLocations.length; i++) {
+ const point = vertexLocations[i].toNDC();
+ vertexCoords[i * 4 + 0] = point.x;
+ vertexCoords[i * 4 + 1] = point.y;
+ vertexCoords[i * 4 + 2] = point.z;
+ vertexCoords[i * 4 + 3] = point.w;
+ }
+ return vertexCoords;
+}
+
+const kDefaultDrawCount = 6;
+class PrimitiveTopologyTest extends GPUTest {
+ makeAttachmentTexture() {
+ return this.device.createTexture({
+ format: kColorFormat,
+ size: { width: kRTSize, height: kRTSize, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ }
+
+ run({
+ topology,
+ indirect,
+ testLocations,
+ primitiveRestart = false,
+ drawCount = kDefaultDrawCount,
+ }) {
+ const colorAttachment = this.makeAttachmentTexture();
+
+ // Color load operator will clear color attachment to zero.
+ const encoder = this.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ let stripIndexFormat = undefined;
+ if (topology === 'triangle-strip' || topology === 'line-strip') {
+ stripIndexFormat = 'uint32';
+ }
+
+ // Draw a primitive using 6 vertices based on the type.
+ // Pixels are generated based on vertex position.
+ // If point, 1 pixel is generated at each vertex location.
+ // Otherwise, >1 pixels could be generated.
+ // Output color is solid green.
+ renderPass.setPipeline(
+ this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @location(0) pos : vec4<f32>
+ ) -> @builtin(position) vec4<f32> {
+ return pos;
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ arrayStride: 4 * Float32Array.BYTES_PER_ELEMENT,
+ attributes: [
+ {
+ format: 'float32x4',
+ offset: 0,
+ shaderLocation: 0,
+ },
+ ],
+ },
+ ],
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: kColorFormat }],
+ },
+ primitive: {
+ topology,
+ stripIndexFormat,
+ },
+ })
+ );
+
+ // Create vertices for the primitive in a vertex buffer and bind it.
+ const vertexCoords = generateVertexBuffer(VertexLocations);
+ const vertexBuffer = this.makeBufferWithContents(vertexCoords, GPUBufferUsage.VERTEX);
+ renderPass.setVertexBuffer(0, vertexBuffer);
+
+ // Restart the strip between [v3, <restart>, v4].
+ if (primitiveRestart) {
+ const indexBuffer = this.makeBufferWithContents(
+ new Uint32Array([0, 1, 2, -1, 3, 4, 5]),
+ GPUBufferUsage.INDEX
+ );
+
+ renderPass.setIndexBuffer(indexBuffer, 'uint32');
+
+ if (indirect) {
+ renderPass.drawIndexedIndirect(
+ this.makeBufferWithContents(
+ new Uint32Array([drawCount + 1, 1, 0, 0, 0]),
+ GPUBufferUsage.INDIRECT
+ ),
+
+ 0
+ );
+ } else {
+ renderPass.drawIndexed(drawCount + 1); // extra index for restart
+ }
+ } else {
+ if (indirect) {
+ renderPass.drawIndirect(
+ this.makeBufferWithContents(
+ new Uint32Array([drawCount, 1, 0, 0]),
+ GPUBufferUsage.INDIRECT
+ ),
+
+ 0
+ );
+ } else {
+ renderPass.draw(drawCount);
+ }
+ }
+
+ renderPass.end();
+
+ this.device.queue.submit([encoder.finish()]);
+
+ for (const testPixel of testLocations) {
+ this.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ kColorFormat,
+ { x: testPixel.location.x, y: testPixel.location.y },
+ { exp: testPixel.color }
+ );
+ }
+ }
+}
+
+export const g = makeTestGroup(PrimitiveTopologyTest);
+
+const topologies = ['point-list', 'line-list', 'line-strip', 'triangle-list', 'triangle-strip'];
+
+g.test('basic')
+ .desc(
+ `Compute test locations for valid and invalid pixels for each topology.
+ If the primitive covers the pixel, the color value will be |kValidPixelColor|.
+ Otherwise, a non-covered pixel will be |kInvalidPixelColor|.
+
+ Params:
+ - topology= {...all topologies}
+ - indirect= {true, false}
+ - primitiveRestart= { true, false } - always false for non-strip topologies
+ `
+ )
+ .params(u =>
+ u //
+ .combine('topology', topologies)
+ .combine('indirect', [false, true])
+ .combine('primitiveRestart', [false, true])
+ .unless(
+ p => p.primitiveRestart && p.topology !== 'line-strip' && p.topology !== 'triangle-strip'
+ )
+ )
+ .fn(t => {
+ t.run({
+ ...t.params,
+ testLocations: getDefaultTestLocations(t.params),
+ });
+ });
+
+g.test('unaligned_vertex_count')
+ .desc(
+ `Test that drawing with a number of vertices that's not a multiple of the vertices a given primitive list topology is not an error. The last primitive is not drawn.
+
+ Params:
+ - topology= {line-list, triangle-list}
+ - indirect= {true, false}
+ - drawCount - number of vertices to draw. A value smaller than the test's default of ${kDefaultDrawCount}.
+ One smaller for line-list. One or two smaller for triangle-list.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('topology', ['line-list', 'triangle-list'])
+ .combine('indirect', [false, true])
+ .expand('drawCount', function* (p) {
+ switch (p.topology) {
+ case 'line-list':
+ yield kDefaultDrawCount - 1;
+ break;
+ case 'triangle-list':
+ yield kDefaultDrawCount - 1;
+ yield kDefaultDrawCount - 2;
+ break;
+ }
+ })
+ )
+ .fn(t => {
+ const testLocations = getDefaultTestLocations({ ...t.params, invalidateLastInList: true });
+ t.run({
+ ...t.params,
+ testLocations,
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js
new file mode 100644
index 0000000000..df44720b16
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/sample_mask.spec.js
@@ -0,0 +1,501 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests that the final sample mask is the logical AND of all the relevant masks.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { TypeF32, TypeU32 } from '../../../util/conversion.js';
+import { makeTextureWithContents } from '../../../util/texture.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+
+const kColors = [
+ // Red
+ new Uint8Array([0xff, 0, 0, 0xff]),
+ // Green
+ new Uint8Array([0, 0xff, 0, 0xff]),
+ // Blue
+ new Uint8Array([0, 0, 0xff, 0xff]),
+ // Yellow
+ new Uint8Array([0xff, 0xff, 0, 0xff]),
+];
+
+const kDepthClearValue = 1.0;
+const kDepthWriteValue = 0.0;
+const kStencilClearValue = 0;
+const kStencilReferenceValue = 0xff;
+
+// Format of the render target and resolve target
+const format = 'rgba8unorm';
+
+// Format of depth stencil attachment
+const depthStencilFormat = 'depth24plus-stencil8';
+
+const kRenderTargetSize = 1;
+
+function hasSample(rasterizationMask, sampleMask, fragmentShaderOutputMask, sampleIndex = 0) {
+ return (rasterizationMask & sampleMask & fragmentShaderOutputMask & (1 << sampleIndex)) > 0;
+}
+
+class F extends GPUTest {
+ async GetTargetTexture(sampleCount, rasterizationMask, sampleMask, fragmentShaderOutputMask) {
+ // Create a 2x2 color texture to sample from
+ // texel 0 - Red
+ // texel 1 - Green
+ // texel 2 - Blue
+ // texel 3 - Yellow
+ const kSampleTextureSize = 2;
+ const sampleTexture = makeTextureWithContents(
+ this.device,
+ TexelView.fromTexelsAsBytes(format, coord => {
+ const id = coord.x + coord.y * kSampleTextureSize;
+ return kColors[id];
+ }),
+ {
+ size: [kSampleTextureSize, kSampleTextureSize, 1],
+ usage:
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ }
+ );
+
+ const sampler = this.device.createSampler({
+ magFilter: 'nearest',
+ minFilter: 'nearest',
+ });
+
+ const fragmentMaskUniformBuffer = this.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
+ });
+ this.trackForCleanup(fragmentMaskUniformBuffer);
+ this.device.queue.writeBuffer(
+ fragmentMaskUniformBuffer,
+ 0,
+ new Uint32Array([fragmentShaderOutputMask])
+ );
+
+ const pipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ struct VertexOutput {
+ @builtin(position) Position : vec4<f32>,
+ @location(0) @interpolate(perspective, sample) fragUV : vec2<f32>,
+ }
+
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 30>(
+ // center quad
+ // only covers pixel center which is sample point when sampleCount === 1
+ // small enough to avoid covering any multi sample points
+ vec2<f32>( 0.2, 0.2),
+ vec2<f32>( 0.2, -0.2),
+ vec2<f32>(-0.2, -0.2),
+ vec2<f32>( 0.2, 0.2),
+ vec2<f32>(-0.2, -0.2),
+ vec2<f32>(-0.2, 0.2),
+
+ // Sub quads are representing rasterization mask and
+ // are slightly scaled to avoid covering the pixel center
+
+ // top-left quad
+ vec2<f32>( -0.01, 1.0),
+ vec2<f32>( -0.01, 0.01),
+ vec2<f32>(-1.0, 0.01),
+ vec2<f32>( -0.01, 1.0),
+ vec2<f32>(-1.0, 0.01),
+ vec2<f32>(-1.0, 1.0),
+
+ // top-right quad
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(1.0, 0.01),
+ vec2<f32>(0.01, 0.01),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(0.01, 0.01),
+ vec2<f32>(0.01, 1.0),
+
+ // bottom-left quad
+ vec2<f32>( -0.01, -0.01),
+ vec2<f32>( -0.01, -1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( -0.01, -0.01),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, -0.01),
+
+ // bottom-right quad
+ vec2<f32>(1.0, -0.01),
+ vec2<f32>(1.0, -1.0),
+ vec2<f32>(0.01, -1.0),
+ vec2<f32>(1.0, -0.01),
+ vec2<f32>(0.01, -1.0),
+ vec2<f32>(0.01, -0.01)
+ );
+
+ var uv = array<vec2<f32>, 30>(
+ // center quad
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(0.0, 0.0),
+
+ // top-left quad (texel 0)
+ vec2<f32>(0.5, 0.0),
+ vec2<f32>(0.5, 0.5),
+ vec2<f32>(0.0, 0.5),
+ vec2<f32>(0.5, 0.0),
+ vec2<f32>(0.0, 0.5),
+ vec2<f32>(0.0, 0.0),
+
+ // top-right quad (texel 1)
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(1.0, 0.5),
+ vec2<f32>(0.5, 0.5),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(0.5, 0.5),
+ vec2<f32>(0.5, 0.0),
+
+ // bottom-left quad (texel 2)
+ vec2<f32>(0.5, 0.5),
+ vec2<f32>(0.5, 1.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(0.5, 0.5),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(0.0, 0.5),
+
+ // bottom-right quad (texel 3)
+ vec2<f32>(1.0, 0.5),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(0.5, 1.0),
+ vec2<f32>(1.0, 0.5),
+ vec2<f32>(0.5, 1.0),
+ vec2<f32>(0.5, 0.5)
+ );
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex], ${kDepthWriteValue}, 1.0);
+ output.fragUV = uv[VertexIndex];
+ return output;
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var mySampler: sampler;
+ @group(0) @binding(1) var myTexture: texture_2d<f32>;
+ @group(0) @binding(2) var<uniform> fragMask: u32;
+
+ struct FragmentOutput {
+ @builtin(sample_mask) mask : u32,
+ @location(0) color : vec4<f32>,
+ }
+
+ @fragment
+ fn main(@location(0) @interpolate(perspective, sample) fragUV: vec2<f32>) -> FragmentOutput {
+ return FragmentOutput(fragMask, textureSample(myTexture, mySampler, fragUV));
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: { topology: 'triangle-list' },
+ multisample: {
+ count: sampleCount,
+ mask: sampleMask,
+ alphaToCoverageEnabled: false,
+ },
+ depthStencil: {
+ format: depthStencilFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'always',
+
+ stencilFront: {
+ compare: 'always',
+ passOp: 'replace',
+ },
+ stencilBack: {
+ compare: 'always',
+ passOp: 'replace',
+ },
+ },
+ });
+
+ const uniformBindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: sampler,
+ },
+ {
+ binding: 1,
+ resource: sampleTexture.createView(),
+ },
+ {
+ binding: 2,
+ resource: {
+ buffer: fragmentMaskUniformBuffer,
+ },
+ },
+ ],
+ });
+
+ const renderTargetTexture = this.device.createTexture({
+ format,
+ size: {
+ width: kRenderTargetSize,
+ height: kRenderTargetSize,
+ depthOrArrayLayers: 1,
+ },
+ sampleCount,
+ mipLevelCount: 1,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ });
+ const resolveTargetTexture =
+ sampleCount === 1
+ ? null
+ : this.device.createTexture({
+ format,
+ size: {
+ width: kRenderTargetSize,
+ height: kRenderTargetSize,
+ depthOrArrayLayers: 1,
+ },
+ sampleCount: 1,
+ mipLevelCount: 1,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const depthStencilTexture = this.device.createTexture({
+ size: {
+ width: kRenderTargetSize,
+ height: kRenderTargetSize,
+ },
+ format: depthStencilFormat,
+ sampleCount,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: renderTargetTexture.createView(),
+ resolveTarget: resolveTargetTexture?.createView(),
+
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: depthStencilTexture.createView(),
+ depthClearValue: kDepthClearValue,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilClearValue: kStencilClearValue,
+ stencilLoadOp: 'clear',
+ stencilStoreOp: 'store',
+ },
+ };
+ const commandEncoder = this.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.setStencilReference(kStencilReferenceValue);
+
+ if (sampleCount === 1) {
+ if ((rasterizationMask & 1) !== 0) {
+ // draw center quad
+ passEncoder.draw(6);
+ }
+ } else {
+ assert(sampleCount === 4);
+ if ((rasterizationMask & 1) !== 0) {
+ // draw top-left quad
+ passEncoder.draw(6, 1, 6);
+ }
+ if ((rasterizationMask & 2) !== 0) {
+ // draw top-right quad
+ passEncoder.draw(6, 1, 12);
+ }
+ if ((rasterizationMask & 4) !== 0) {
+ // draw bottom-left quad
+ passEncoder.draw(6, 1, 18);
+ }
+ if ((rasterizationMask & 8) !== 0) {
+ // draw bottom-right quad
+ passEncoder.draw(6, 1, 24);
+ }
+ }
+ passEncoder.end();
+ this.device.queue.submit([commandEncoder.finish()]);
+
+ return {
+ color: renderTargetTexture,
+ depthStencil: depthStencilTexture,
+ };
+ }
+
+ CheckColorAttachmentResult(
+ texture,
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ ) {
+ const buffer = this.copySinglePixelTextureToBufferUsingComputePass(
+ TypeF32, // correspond to 'rgba8unorm' format
+ 4,
+ texture.createView(),
+ sampleCount
+ );
+
+ const expectedDstData = new Float32Array(sampleCount * 4);
+ if (sampleCount === 1) {
+ if (hasSample(rasterizationMask, sampleMask, fragmentShaderOutputMask)) {
+ // Texel 3 is sampled at the pixel center
+ expectedDstData[0] = kColors[3][0] / 0xff;
+ expectedDstData[1] = kColors[3][1] / 0xff;
+ expectedDstData[2] = kColors[3][2] / 0xff;
+ expectedDstData[3] = kColors[3][3] / 0xff;
+ }
+ } else {
+ for (let i = 0; i < sampleCount; i++) {
+ if (hasSample(rasterizationMask, sampleMask, fragmentShaderOutputMask, i)) {
+ const o = i * 4;
+ expectedDstData[o + 0] = kColors[i][0] / 0xff;
+ expectedDstData[o + 1] = kColors[i][1] / 0xff;
+ expectedDstData[o + 2] = kColors[i][2] / 0xff;
+ expectedDstData[o + 3] = kColors[i][3] / 0xff;
+ }
+ }
+ }
+
+ this.expectGPUBufferValuesEqual(buffer, expectedDstData);
+ }
+
+ CheckDepthStencilResult(
+ aspect,
+ depthStencilTexture,
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ ) {
+ const buffer = this.copySinglePixelTextureToBufferUsingComputePass(
+ // Use f32 as the scalar type for depth (depth24plus, depth32float)
+ // Use u32 as the scalar type for stencil (stencil8)
+ aspect === 'depth-only' ? TypeF32 : TypeU32,
+ 1,
+ depthStencilTexture.createView({ aspect }),
+ sampleCount
+ );
+
+ const expectedDstData =
+ aspect === 'depth-only' ? new Float32Array(sampleCount) : new Uint32Array(sampleCount);
+ for (let i = 0; i < sampleCount; i++) {
+ const s = hasSample(rasterizationMask, sampleMask, fragmentShaderOutputMask, i);
+ if (aspect === 'depth-only') {
+ expectedDstData[i] = s ? kDepthWriteValue : kDepthClearValue;
+ } else {
+ expectedDstData[i] = s ? kStencilReferenceValue : kStencilClearValue;
+ }
+ }
+ this.expectGPUBufferValuesEqual(buffer, expectedDstData);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('final_output')
+ .desc(
+ `
+Tests that the final sample mask is the logical AND of all the relevant masks -- meaning that the samples
+not included in the final mask are discarded on any attachments including
+- color outputs
+- depth tests
+- stencil operations
+
+The test draws 0/1/1+ textured quads of which each sample in the standard 4-sample pattern results in a different color:
+- Sample 0, Texel 0, top-left: Red
+- Sample 1, Texel 1, top-left: Green
+- Sample 2, Texel 2, top-left: Blue
+- Sample 3, Texel 3, top-left: Yellow
+
+The test checks each sample value of the render target texture and depth stencil texture using a compute pass to
+textureLoad each sample index from the texture and write to a storage buffer to compare with expected values.
+
+- for sampleCount = { 1, 4 } and various combinations of:
+ - rasterization mask = { 0, ..., 2 ** sampleCount - 1 }
+ - sample mask = { 0, 0b0001, 0b0010, 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b11110 }
+ - fragment shader output @builtin(sample_mask) = { 0, 0b0001, 0b0010, 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b11110 }
+- [choosing 0b11110 because the 5th bit should be ignored]
+`
+ )
+ .params(u =>
+ u
+ .combine('sampleCount', [1, 4])
+ .expand('rasterizationMask', function* (p) {
+ for (let i = 0, len = 2 ** p.sampleCount - 1; i <= len; i++) {
+ yield i;
+ }
+ })
+ .beginSubcases()
+ .combine('sampleMask', [0, 0b0001, 0b0010, 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b11110])
+ .combine('fragmentShaderOutputMask', [
+ 0,
+ 0b0001,
+ 0b0010,
+ 0b0111,
+ 0b1011,
+ 0b1101,
+ 0b1110,
+ 0b1111,
+ 0b11110,
+ ])
+ )
+ .fn(async t => {
+ const { sampleCount, rasterizationMask, sampleMask, fragmentShaderOutputMask } = t.params;
+
+ const { color, depthStencil } = await t.GetTargetTexture(
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ );
+
+ t.CheckColorAttachmentResult(
+ color,
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ );
+
+ t.CheckDepthStencilResult(
+ 'depth-only',
+ depthStencil,
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ );
+
+ t.CheckDepthStencilResult(
+ 'stencil-only',
+ depthStencil,
+ sampleCount,
+ rasterizationMask,
+ sampleMask,
+ fragmentShaderOutputMask
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/vertex_only_render_pipeline.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/vertex_only_render_pipeline.spec.js
new file mode 100644
index 0000000000..eb6e361196
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/render_pipeline/vertex_only_render_pipeline.spec.js
@@ -0,0 +1,30 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test vertex-only render pipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+class F extends GPUTest {}
+
+export const g = makeTestGroup(F);
+
+g.test('draw_depth_and_stencil_with_vertex_only_pipeline')
+ .desc(
+ `
+TODO:
+- Test drawing depth and stencil with vertex-only render pipelines by
+ 1. Create a color attachment and depth-stencil attachment of 4 pixels in a line, clear the color
+ to RGBA(0.0, 0.0, 0.0, 0.0), depth to 0.0 and stencil to 0x0
+ 2. Use a depth and stencil test disabled vertex-only render pipeline to modify the depth of middle
+ 2 pixels to 0.5, while leaving stencil unchanged
+ 3. Use another depth and stencil test disabled vertex-only render pipeline to modify the stencil
+ of right 2 pixels to 0x1, while leaving depth unchanged
+ 4. Use a complete render pipeline to draw all 4 pixels with color RGBA(0.0, 1.0, 0.0, 1.0), but
+ with depth test requiring depth no less than 0.5 and stencil test requiring stencil equals to 0x1
+ 5. Validate that only the third pixel is of color RGBA(0.0, 1.0, 0.0, 1.0), and all other pixels
+ are RGBA(0.0, 0.0, 0.0, 0.0).
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/basic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/basic.spec.js
new file mode 100644
index 0000000000..f725586012
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/basic.spec.js
@@ -0,0 +1,357 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Basic command buffer rendering tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { now } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsEqual } from '../../../util/check_contents.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('clear').fn(async t => {
+ const dst = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const colorAttachment = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dst, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(dst, new Uint8Array([0x00, 0xff, 0x00, 0xff]));
+});
+
+g.test('fullscreen_quad').fn(async t => {
+ const dst = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const colorAttachment = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, -3.0),
+ vec2<f32>(3.0, 1.0),
+ vec2<f32>(-1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dst, bytesPerRow: 256 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 }
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(dst, new Uint8Array([0x00, 0xff, 0x00, 0xff]));
+});
+
+g.test('large_draw')
+ .desc(
+ `Test reasonably-sized large {draw, drawIndexed} (see also stress tests).
+
+ Tests that draw calls behave reasonably with large vertex counts for
+ non-indexed draws, large index counts for indexed draws, and large instance
+ counts in both cases. Various combinations of these counts are tested with
+ both direct and indirect draw calls.
+
+ Draw call sizes are increased incrementally over these parameters until we the
+ run out of values or completion of a draw call exceeds a fixed time limit of
+ 100ms.
+
+ To validate that the drawn vertices actually made it though the pipeline on
+ each draw call, we render a 3x3 target with the positions of the first and
+ last vertices of the first and last instances in different respective corners,
+ and everything else positioned to cover only one of the intermediate
+ fragments. If the output image is completely yellow, then we can reasonably
+ infer that all vertices were drawn.
+
+ Params:
+ - indexed= {true, false} - whether to test indexed or non-indexed draw calls
+ - indirect= {true, false} - whether to use indirect or direct draw calls`
+ )
+ .params(u =>
+ u //
+ .combine('indexed', [true, false])
+ .combine('indirect', [true, false])
+ )
+ .fn(async t => {
+ const { indexed, indirect } = t.params;
+
+ const kBytesPerRow = 256;
+ const dst = t.device.createBuffer({
+ size: 3 * kBytesPerRow,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const paramsBuffer = t.device.createBuffer({
+ size: 8,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+
+ const indirectBuffer = t.device.createBuffer({
+ size: 20,
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST,
+ });
+ const writeIndirectParams = (count, instanceCount) => {
+ const params = new Uint32Array(5);
+ params[0] = count; // Vertex or index count
+ params[1] = instanceCount;
+ params[2] = 0; // First vertex or index
+ params[3] = 0; // First instance (non-indexed) or base vertex (indexed)
+ params[4] = 0; // First instance (indexed)
+ t.device.queue.writeBuffer(indirectBuffer, 0, params, 0, 5);
+ };
+
+ let indexBuffer = null;
+ if (indexed) {
+ const kMaxIndices = 16 * 1024 * 1024;
+ indexBuffer = t.device.createBuffer({
+ size: kMaxIndices * Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(indexBuffer);
+ const indexData = new Uint32Array(indexBuffer.getMappedRange());
+ for (let i = 0; i < kMaxIndices; ++i) {
+ indexData[i] = i;
+ }
+ indexBuffer.unmap();
+ }
+
+ const colorAttachment = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 3, height: 3, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const bgLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.VERTEX,
+ buffer: {},
+ },
+ ],
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: bgLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: paramsBuffer },
+ },
+ ],
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: t.device.createPipelineLayout({ bindGroupLayouts: [bgLayout] }),
+
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Params {
+ numVertices: u32,
+ numInstances: u32,
+ };
+
+ fn selectValue(index: u32, maxIndex: u32) -> f32 {
+ let highOrMid = select(0.0, 2.0 / 3.0, index == maxIndex - 1u);
+ return select(highOrMid, -2.0 / 3.0, index == 0u);
+ }
+
+ @group(0) @binding(0) var<uniform> params: Params;
+
+ @vertex fn main(
+ @builtin(vertex_index) v: u32,
+ @builtin(instance_index) i: u32)
+ -> @builtin(position) vec4<f32> {
+ let x = selectValue(v, params.numVertices);
+ let y = -selectValue(i, params.numInstances);
+ return vec4<f32>(x, y, 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 1.0, 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+
+ const runPipeline = (numVertices, numInstances) => {
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 0.0, g: 0.0, b: 1.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ if (indexBuffer !== null) {
+ pass.setIndexBuffer(indexBuffer, 'uint32');
+ }
+
+ if (indirect) {
+ writeIndirectParams(numVertices, numInstances);
+ if (indexed) {
+ pass.drawIndexedIndirect(indirectBuffer, 0);
+ } else {
+ pass.drawIndirect(indirectBuffer, 0);
+ }
+ } else {
+ if (indexed) {
+ pass.drawIndexed(numVertices, numInstances);
+ } else {
+ pass.draw(numVertices, numInstances);
+ }
+ }
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { buffer: dst, bytesPerRow: kBytesPerRow },
+ { width: 3, height: 3, depthOrArrayLayers: 1 }
+ );
+
+ const params = new Uint32Array([numVertices, numInstances]);
+ t.device.queue.writeBuffer(paramsBuffer, 0, params, 0, 2);
+ t.device.queue.submit([encoder.finish()]);
+
+ const yellow = [0xff, 0xff, 0x00, 0xff];
+ const allYellow = new Uint8Array([...yellow, ...yellow, ...yellow]);
+ for (const row of [0, 1, 2]) {
+ t.expectGPUBufferValuesPassCheck(dst, data => checkElementsEqual(data, allYellow), {
+ srcByteOffset: row * 256,
+ type: Uint8Array,
+ typedLength: 12,
+ });
+ }
+ };
+
+ // If any iteration takes longer than this, we stop incrementing along that
+ // branch and move on to the next instance count. Note that the max
+ // supported vertex count for any iteration is 2**24 due to our choice of
+ // index buffer size.
+ const maxDurationMs = 100;
+ const counts = [
+ {
+ numInstances: 4,
+ vertexCounts: [2 ** 10, 2 ** 16, 2 ** 18, 2 ** 20, 2 ** 22, 2 ** 24],
+ },
+ {
+ numInstances: 2 ** 8,
+ vertexCounts: [2 ** 10, 2 ** 16, 2 ** 18, 2 ** 20, 2 ** 22],
+ },
+ {
+ numInstances: 2 ** 10,
+ vertexCounts: [2 ** 8, 2 ** 10, 2 ** 12, 2 ** 16, 2 ** 18, 2 ** 20],
+ },
+ {
+ numInstances: 2 ** 16,
+ vertexCounts: [2 ** 4, 2 ** 8, 2 ** 10, 2 ** 12, 2 ** 14],
+ },
+ {
+ numInstances: 2 ** 20,
+ vertexCounts: [2 ** 4, 2 ** 8, 2 ** 10],
+ },
+ ];
+
+ for (const { numInstances, vertexCounts } of counts) {
+ for (const numVertices of vertexCounts) {
+ const start = now();
+ runPipeline(numVertices, numInstances);
+ await t.device.queue.onSubmittedWorkDone();
+ const duration = now() - start;
+ if (duration >= maxDurationMs) {
+ break;
+ }
+ }
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js
new file mode 100644
index 0000000000..0efeb39c3a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/color_target_state.spec.js
@@ -0,0 +1,878 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test blending results.
+
+TODO:
+- Test result for all combinations of args (make sure each case is distinguishable from others
+- Test underflow/overflow has consistent behavior
+- ?
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../common/util/util.js';
+import {
+ kBlendFactors,
+ kBlendOperations,
+ kEncodableTextureFormats,
+ kTextureFormatInfo,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { float32ToFloat16Bits } from '../../../util/conversion.js';
+import { clamp } from '../../../util/math.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+
+class BlendingTest extends GPUTest {
+ createRenderPipelineForTest(colorTargetState) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ fragment: {
+ targets: [colorTargetState],
+ module: this.device.createShaderModule({
+ code: `
+ struct Params {
+ color : vec4<f32>
+ }
+ @group(0) @binding(0) var<uniform> params : Params;
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return params.color;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(3.0, -1.0),
+ vec2<f32>(-1.0, 3.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ }
+
+ createBindGroupForTest(layout, data) {
+ return this.device.createBindGroup({
+ layout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: this.makeBufferWithContents(data, GPUBufferUsage.UNIFORM),
+ },
+ },
+ ],
+ });
+ }
+}
+
+export const g = makeTestGroup(BlendingTest);
+
+function mapColor(col, f) {
+ return {
+ r: f(col.r, 'r'),
+ g: f(col.g, 'g'),
+ b: f(col.b, 'b'),
+ a: f(col.a, 'a'),
+ };
+}
+
+function computeBlendFactor(src, dst, blendColor, factor) {
+ switch (factor) {
+ case 'zero':
+ return { r: 0, g: 0, b: 0, a: 0 };
+ case 'one':
+ return { r: 1, g: 1, b: 1, a: 1 };
+ case 'src':
+ return { ...src };
+ case 'one-minus-src':
+ return mapColor(src, v => 1 - v);
+ case 'src-alpha':
+ return mapColor(src, () => src.a);
+ case 'one-minus-src-alpha':
+ return mapColor(src, () => 1 - src.a);
+ case 'dst':
+ return { ...dst };
+ case 'one-minus-dst':
+ return mapColor(dst, v => 1 - v);
+ case 'dst-alpha':
+ return mapColor(dst, () => dst.a);
+ case 'one-minus-dst-alpha':
+ return mapColor(dst, () => 1 - dst.a);
+ case 'src-alpha-saturated': {
+ const f = Math.min(src.a, 1 - dst.a);
+ return { r: f, g: f, b: f, a: 1 };
+ }
+ case 'constant':
+ assert(blendColor !== undefined);
+ return { ...blendColor };
+ case 'one-minus-constant':
+ assert(blendColor !== undefined);
+ return mapColor(blendColor, v => 1 - v);
+ default:
+ unreachable();
+ }
+}
+
+function computeBlendOperation(src, srcFactor, dst, dstFactor, operation) {
+ switch (operation) {
+ case 'add':
+ return mapColor(src, (_, k) => srcFactor[k] * src[k] + dstFactor[k] * dst[k]);
+ case 'max':
+ return mapColor(src, (_, k) => Math.max(src[k], dst[k]));
+ case 'min':
+ return mapColor(src, (_, k) => Math.min(src[k], dst[k]));
+ case 'reverse-subtract':
+ return mapColor(src, (_, k) => dstFactor[k] * dst[k] - srcFactor[k] * src[k]);
+ case 'subtract':
+ return mapColor(src, (_, k) => srcFactor[k] * src[k] - dstFactor[k] * dst[k]);
+ }
+}
+
+g.test('blending,GPUBlendComponent')
+ .desc(
+ `Test all combinations of parameters for GPUBlendComponent.
+
+ Tests that parameters are correctly passed to the backend API and blend computations
+ are done correctly by blending a single pixel. The test uses rgba16float as the format
+ to avoid checking clamping behavior (tested in api,operation,rendering,blending:clamp,*).
+
+ Params:
+ - component= {color, alpha} - whether to test blending the color or the alpha component.
+ - srcFactor= {...all GPUBlendFactors}
+ - dstFactor= {...all GPUBlendFactors}
+ - operation= {...all GPUBlendOperations}`
+ )
+ .params(u =>
+ u //
+ .combine('component', ['color', 'alpha'])
+ .combine('srcFactor', kBlendFactors)
+ .combine('dstFactor', kBlendFactors)
+ .combine('operation', kBlendOperations)
+ .filter(t => {
+ if (t.operation === 'min' || t.operation === 'max') {
+ return t.srcFactor === 'one' && t.dstFactor === 'one';
+ }
+ return true;
+ })
+ .beginSubcases()
+ .combine('srcColor', [{ r: 0.11, g: 0.61, b: 0.81, a: 0.44 }])
+ .combine('dstColor', [
+ { r: 0.51, g: 0.22, b: 0.71, a: 0.33 },
+ { r: 0.09, g: 0.73, b: 0.93, a: 0.81 },
+ ])
+ .expand('blendConstant', p => {
+ const needsBlendConstant =
+ p.srcFactor === 'one-minus-constant' ||
+ p.srcFactor === 'constant' ||
+ p.dstFactor === 'one-minus-constant' ||
+ p.dstFactor === 'constant';
+ return needsBlendConstant ? [{ r: 0.91, g: 0.82, b: 0.73, a: 0.64 }] : [undefined];
+ })
+ )
+ .fn(t => {
+ const textureFormat = 'rgba16float';
+ const srcColor = t.params.srcColor;
+ const dstColor = t.params.dstColor;
+ const blendConstant = t.params.blendConstant;
+
+ const srcFactor = computeBlendFactor(srcColor, dstColor, blendConstant, t.params.srcFactor);
+ const dstFactor = computeBlendFactor(srcColor, dstColor, blendConstant, t.params.dstFactor);
+
+ const expectedColor = computeBlendOperation(
+ srcColor,
+ srcFactor,
+ dstColor,
+ dstFactor,
+ t.params.operation
+ );
+
+ switch (t.params.component) {
+ case 'color':
+ expectedColor.a = srcColor.a;
+ break;
+ case 'alpha':
+ expectedColor.r = srcColor.r;
+ expectedColor.g = srcColor.g;
+ expectedColor.b = srcColor.b;
+ break;
+ }
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ fragment: {
+ targets: [
+ {
+ format: textureFormat,
+ blend: {
+ // Set both color/alpha to defaults...
+ color: {},
+ alpha: {},
+ // ... but then override the component we're testing.
+ [t.params.component]: {
+ srcFactor: t.params.srcFactor,
+ dstFactor: t.params.dstFactor,
+ operation: t.params.operation,
+ },
+ },
+ },
+ ],
+
+ module: t.device.createShaderModule({
+ code: `
+struct Uniform {
+ color: vec4<f32>
+};
+@group(0) @binding(0) var<uniform> u : Uniform;
+
+@fragment fn main() -> @location(0) vec4<f32> {
+ return u.color;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+@vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [1, 1, 1],
+ format: textureFormat,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: dstColor,
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(pipeline);
+ if (blendConstant) {
+ renderPass.setBlendConstant(blendConstant);
+ }
+ renderPass.setBindGroup(
+ 0,
+ t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: t.makeBufferWithContents(
+ new Float32Array([srcColor.r, srcColor.g, srcColor.b, srcColor.a]),
+ GPUBufferUsage.UNIFORM
+ ),
+ },
+ },
+ ],
+ })
+ );
+
+ renderPass.draw(1);
+ renderPass.end();
+
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ const tolerance = 0.003;
+ const expectedLow = mapColor(expectedColor, v => v - tolerance);
+ const expectedHigh = mapColor(expectedColor, v => v + tolerance);
+
+ t.expectSinglePixelBetweenTwoValuesFloat16In2DTexture(
+ renderTarget,
+ textureFormat,
+ { x: 0, y: 0 },
+ {
+ exp: [
+ // Use Uint16Array to store Float16 value bits
+ new Uint16Array(
+ [expectedLow.r, expectedLow.g, expectedLow.b, expectedLow.a].map(float32ToFloat16Bits)
+ ),
+
+ new Uint16Array(
+ [expectedHigh.r, expectedHigh.g, expectedHigh.b, expectedHigh.a].map(
+ float32ToFloat16Bits
+ )
+ ),
+ ],
+ }
+ );
+ });
+
+const kBlendableFormats = kEncodableTextureFormats.filter(f => {
+ const info = kTextureFormatInfo[f];
+ return info.renderable && info.sampleType === 'float';
+});
+
+g.test('blending,formats')
+ .desc(
+ `Test blending results works for all formats that support it, and that blending is not applied
+ for formats that do not. Blending should be done in linear space for srgb formats.`
+ )
+ .params(u =>
+ u //
+ .combine('format', kBlendableFormats)
+ )
+ .fn(async t => {
+ const { format } = t.params;
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ fragment: {
+ targets: [
+ {
+ format,
+ blend: {
+ color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
+ alpha: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
+ },
+ },
+ ],
+
+ module: t.device.createShaderModule({
+ code: `
+@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.4, 0.4, 0.4, 0.4);
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+@vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [1, 1, 1],
+ format,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: { r: 0.2, g: 0.2, b: 0.2, a: 0.2 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(pipeline);
+ renderPass.draw(1);
+ renderPass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ const expColor = { R: 0.6, G: 0.6, B: 0.6, A: 0.6 };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [1, 1, 1],
+ { expTexelView },
+ {
+ maxDiffULPsForNormFormat: 1,
+ maxDiffULPsForFloatFormat: 1,
+ }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('blend_constant,initial')
+ .desc(`Test that the blend constant is set to [0,0,0,0] at the beginning of a pass.`)
+ .fn(async t => {
+ const format = 'rgba8unorm';
+ const kSize = 1;
+ const kWhiteColorData = new Float32Array([255, 255, 255, 255]);
+
+ const blendComponent = { srcFactor: 'constant', dstFactor: 'one', operation: 'add' };
+ const testPipeline = t.createRenderPipelineForTest({
+ format,
+ blend: { color: blendComponent, alpha: blendComponent },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [kSize, kSize],
+ format,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kWhiteColorData)
+ );
+
+ renderPass.draw(3);
+ // Draw [1,1,1,1] with `src * constant + dst * 1`.
+ // The blend constant defaults to [0,0,0,0], so the result is
+ // `[1,1,1,1] * [0,0,0,0] + [0,0,0,0] * 1` = [0,0,0,0].
+ renderPass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ // Check that the initial blend constant is black(0,0,0,0) after setting testPipeline which has
+ // a white color buffer data.
+ const expColor = { R: 0, G: 0, B: 0, A: 0 };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [kSize, kSize],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('blend_constant,setting')
+ .desc(`Test that setting the blend constant to the RGBA values works at the beginning of a pass.`)
+ .paramsSubcasesOnly([
+ { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
+ { r: 0.5, g: 1.0, b: 0.5, a: 0.0 },
+ { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ ])
+ .fn(async t => {
+ const { r, g, b, a } = t.params;
+
+ const format = 'rgba8unorm';
+ const kSize = 1;
+ const kWhiteColorData = new Float32Array([255, 255, 255, 255]);
+
+ const blendComponent = { srcFactor: 'constant', dstFactor: 'one', operation: 'add' };
+ const testPipeline = t.createRenderPipelineForTest({
+ format,
+ blend: { color: blendComponent, alpha: blendComponent },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [kSize, kSize],
+ format,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBlendConstant({ r, g, b, a });
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kWhiteColorData)
+ );
+
+ renderPass.draw(3);
+ // Draw [1,1,1,1] with `src * constant + dst * 1`. The blend constant to [r,g,b,a], so the
+ // result is `[1,1,1,1] * [r,g,b,a] + [0,0,0,0] * 1` = [r,g,b,a].
+ renderPass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ // Check that the blend constant is the same as the given constant after setting the constant
+ // via setBlendConstant.
+ const expColor = { R: r, G: g, B: b, A: a };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [kSize, kSize],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('blend_constant,not_inherited')
+ .desc(`Test that the blending constant is not inherited between render passes.`)
+ .fn(async t => {
+ const format = 'rgba8unorm';
+ const kSize = 1;
+ const kWhiteColorData = new Float32Array([255, 255, 255, 255]);
+
+ const blendComponent = { srcFactor: 'constant', dstFactor: 'one', operation: 'add' };
+ const testPipeline = t.createRenderPipelineForTest({
+ format,
+ blend: { color: blendComponent, alpha: blendComponent },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [kSize, kSize],
+ format,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ {
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBlendConstant({ r: 1.0, g: 1.0, b: 1.0, a: 1.0 }); // Set to white color.
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kWhiteColorData)
+ );
+
+ renderPass.draw(3);
+ // Draw [1,1,1,1] with `src * constant + dst * 1`. The blend constant to [1,1,1,1], so the
+ // result is `[1,1,1,1] * [1,1,1,1] + [0,0,0,0] * 1` = [1,1,1,1].
+ renderPass.end();
+ }
+ {
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kWhiteColorData)
+ );
+
+ renderPass.draw(3);
+ // Draw [1,1,1,1] with `src * constant + dst * 1`. The blend constant defaults to [0,0,0,0],
+ // so the result is `[1,1,1,1] * [0,0,0,0] + [0,0,0,0] * 1` = [0,0,0,0].
+ renderPass.end();
+ }
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ // Check that the blend constant is not inherited from the first render pass.
+ const expColor = { R: 0, G: 0, B: 0, A: 0 };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [kSize, kSize],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+const kColorWriteCombinations = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+
+g.test('color_write_mask,channel_work')
+ .desc(
+ `
+ Test that the color write mask works with the zero channel, a single channel, multiple channels,
+ and all channels.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('mask', kColorWriteCombinations)
+ )
+ .fn(async t => {
+ const { mask } = t.params;
+
+ const format = 'rgba8unorm';
+ const kSize = 1;
+
+ let r = 0,
+ g = 0,
+ b = 0,
+ a = 0;
+ if (mask & GPUConst.ColorWrite.RED) {
+ r = 1;
+ }
+ if (mask & GPUConst.ColorWrite.GREEN) {
+ g = 1;
+ }
+ if (mask & GPUConst.ColorWrite.BLUE) {
+ b = 1;
+ }
+ if (mask & GPUConst.ColorWrite.ALPHA) {
+ a = 1;
+ }
+
+ const testPipeline = t.createRenderPipelineForTest({
+ format,
+ writeMask: mask,
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [kSize, kSize],
+ format,
+ });
+
+ const kBaseColorData = new Float32Array([32, 64, 128, 192]);
+
+ const commandEncoder = t.device.createCommandEncoder();
+ {
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kBaseColorData)
+ );
+
+ renderPass.draw(3);
+ renderPass.end();
+ }
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ const expColor = { R: r, G: g, B: b, A: a };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [kSize, kSize],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('color_write_mask,blending_disabled')
+ .desc(
+ `Test that the color write mask works when blending is disabled or set to the defaults
+ (which has the same blending result).`
+ )
+ .params(u => u.combine('disabled', [false, true]))
+ .fn(async t => {
+ const format = 'rgba8unorm';
+ const kSize = 1;
+
+ const blend = t.params.disabled ? undefined : { color: {}, alpha: {} };
+
+ const testPipeline = t.createRenderPipelineForTest({
+ format,
+ blend,
+ writeMask: GPUColorWrite.RED,
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [kSize, kSize],
+ format,
+ });
+
+ const kBaseColorData = new Float32Array([32, 64, 128, 192]);
+
+ const commandEncoder = t.device.createCommandEncoder();
+ {
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(testPipeline);
+ renderPass.setBindGroup(
+ 0,
+ t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kBaseColorData)
+ );
+
+ // Draw [1,1,1,1] with `src * 1 + dst * 0`. So the
+ // result is `[1,1,1,1] * [1,1,1,1] + [0,0,0,0] * 0` = [1,1,1,1].
+ renderPass.draw(3);
+ renderPass.end();
+ }
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ const expColor = { R: 1, G: 0, B: 0, A: 0 };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [kSize, kSize],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('blending,clamping')
+ .desc(
+ `
+ Test that clamping occurs at the correct points in the blend process: src value, src factor, dst
+ factor, and output.
+ - TODO: Need to test snorm formats.
+ - TODO: Need to test src value, srcFactor and dstFactor.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', ['rgba8unorm', 'rg16float'])
+ .combine('srcValue', [0.4, 0.6, 0.8, 1.0])
+ .combine('dstValue', [0.2, 0.4])
+ )
+ .fn(async t => {
+ const { format, srcValue, dstValue } = t.params;
+
+ const blendComponent = { srcFactor: 'one', dstFactor: 'one', operation: 'add' };
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ fragment: {
+ targets: [
+ {
+ format,
+ blend: {
+ color: blendComponent,
+ alpha: blendComponent,
+ },
+ },
+ ],
+
+ module: t.device.createShaderModule({
+ code: `
+@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(${srcValue}, ${srcValue}, ${srcValue}, ${srcValue});
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+@vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const renderTarget = t.device.createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ size: [1, 1, 1],
+ format,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: { r: dstValue, g: dstValue, b: dstValue, a: dstValue },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(pipeline);
+ renderPass.draw(1);
+ renderPass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ let expValue;
+ switch (format) {
+ case 'rgba8unorm': // unorm types should clamp if the sum of srcValue and dstValue exceeds 1.
+ expValue = clamp(srcValue + dstValue, { min: 0, max: 1 });
+ break;
+ case 'rg16float': // float format types doesn't clamp.
+ expValue = srcValue + dstValue;
+ break;
+ }
+
+ const expColor = { R: expValue, G: expValue, B: expValue, A: expValue };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: renderTarget },
+ [1, 1, 1],
+ { expTexelView },
+ {
+ maxDiffULPsForNormFormat: 1,
+ maxDiffULPsForFloatFormat: 1,
+ }
+ );
+
+ t.expectOK(result);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js
new file mode 100644
index 0000000000..7a95df4944
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth.spec.js
@@ -0,0 +1,546 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test related to depth buffer, depth op, compare func, etc.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+
+import { kDepthStencilFormats, kTextureFormatInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+
+const backgroundColor = [0x00, 0x00, 0x00, 0xff];
+const triangleColor = [0xff, 0xff, 0xff, 0xff];
+
+const kBaseColor = new Float32Array([1.0, 1.0, 1.0, 1.0]);
+const kRedStencilColor = new Float32Array([1.0, 0.0, 0.0, 1.0]);
+const kGreenStencilColor = new Float32Array([0.0, 1.0, 0.0, 1.0]);
+
+class DepthTest extends GPUTest {
+ runDepthStateTest(testStates, expectedColor) {
+ const renderTargetFormat = 'rgba8unorm';
+
+ const renderTarget = this.device.createTexture({
+ format: renderTargetFormat,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const depthStencilFormat = 'depth24plus-stencil8';
+ const depthTexture = this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: depthStencilFormat,
+ sampleCount: 1,
+ mipLevelCount: 1,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST,
+ });
+
+ const depthStencilAttachment = {
+ view: depthTexture.createView(),
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilLoadOp: 'load',
+ stencilStoreOp: 'store',
+ };
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ loadOp: 'load',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+
+ // Draw a triangle with the given depth state, color, and depth.
+ for (const test of testStates) {
+ const testPipeline = this.createRenderPipelineForTest(test.state, test.depth);
+ pass.setPipeline(testPipeline);
+ pass.setBindGroup(
+ 0,
+ this.createBindGroupForTest(testPipeline.getBindGroupLayout(0), test.color)
+ );
+
+ pass.draw(1);
+ }
+
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ const expColor = {
+ R: expectedColor[0],
+ G: expectedColor[1],
+ B: expectedColor[2],
+ A: expectedColor[3],
+ };
+ const expTexelView = TexelView.fromTexelsAsColors(renderTargetFormat, coords => expColor);
+
+ const result = textureContentIsOKByT2B(
+ this,
+ { texture: renderTarget },
+ [1, 1],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ this.eventualExpectOK(result);
+ this.trackForCleanup(renderTarget);
+ }
+
+ createRenderPipelineForTest(depthStencil, depth) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, ${depth}, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ targets: [{ format: 'rgba8unorm' }],
+ module: this.device.createShaderModule({
+ code: `
+ struct Params {
+ color : vec4<f32>
+ }
+ @group(0) @binding(0) var<uniform> params : Params;
+
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(params.color);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ primitive: { topology: 'point-list' },
+ depthStencil,
+ });
+ }
+
+ createBindGroupForTest(layout, data) {
+ return this.device.createBindGroup({
+ layout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: this.makeBufferWithContents(data, GPUBufferUsage.UNIFORM),
+ },
+ },
+ ],
+ });
+ }
+}
+
+export const g = makeTestGroup(DepthTest);
+
+g.test('depth_disabled')
+ .desc('Tests render results with depth test disabled.')
+ .fn(async t => {
+ const depthSpencilFormat = 'depth24plus-stencil8';
+ const state = { format: depthSpencilFormat };
+
+ const testStates = [
+ { state, color: kBaseColor, depth: 0.0 },
+ { state, color: kRedStencilColor, depth: 0.5 },
+ { state, color: kGreenStencilColor, depth: 1.0 },
+ ];
+
+ // Test that for all combinations and ensure the last triangle drawn is the one visible
+ // regardless of depth testing.
+ for (let last = 0; last < 3; ++last) {
+ const i = (last + 1) % 3;
+ const j = (last + 2) % 3;
+
+ t.runDepthStateTest([testStates[i], testStates[j], testStates[last]], testStates[last].color);
+ t.runDepthStateTest([testStates[j], testStates[i], testStates[last]], testStates[last].color);
+ }
+ });
+
+g.test('depth_write_disabled')
+ .desc(
+ `
+ Test that depthWriteEnabled behaves as expected.
+ If enabled, a depth value of 0.0 is written.
+ If disabled, it's not written, so it keeps the previous value of 1.0.
+ Use a depthCompare: 'equal' check at the end to check the value.
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([
+ { depthWriteEnabled: false, lastDepth: 0.0, _expectedColor: kRedStencilColor },
+ { depthWriteEnabled: true, lastDepth: 0.0, _expectedColor: kGreenStencilColor },
+ { depthWriteEnabled: false, lastDepth: 1.0, _expectedColor: kGreenStencilColor },
+ { depthWriteEnabled: true, lastDepth: 1.0, _expectedColor: kRedStencilColor },
+ ])
+ )
+ .fn(async t => {
+ const { depthWriteEnabled, lastDepth, _expectedColor } = t.params;
+
+ const depthSpencilFormat = 'depth24plus-stencil8';
+
+ const stencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ depthFailOp: 'keep',
+ passOp: 'keep',
+ };
+
+ const baseState = {
+ format: depthSpencilFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'always',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ stencilReadMask: 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const depthWriteState = {
+ format: depthSpencilFormat,
+ depthWriteEnabled,
+ depthCompare: 'always',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ stencilReadMask: 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const checkState = {
+ format: depthSpencilFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'equal',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ stencilReadMask: 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const testStates = [
+ // Draw a base point with depth write enabled.
+ { state: baseState, color: kBaseColor, depth: 1.0 },
+ // Draw a second point without depth write enabled.
+ { state: depthWriteState, color: kRedStencilColor, depth: 0.0 },
+ // Draw a third point which should occlude the second even though it is behind it.
+ { state: checkState, color: kGreenStencilColor, depth: lastDepth },
+ ];
+
+ t.runDepthStateTest(testStates, _expectedColor);
+ });
+
+g.test('depth_test_fail')
+ .desc(
+ `
+ Test that render results on depth test failure cases with 'less' depthCompare operation and
+ depthWriteEnabled is true.
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([
+ { secondDepth: 1.0, lastDepth: 2.0, _expectedColor: kBaseColor }, // fail -> fail.
+ { secondDepth: 0.0, lastDepth: 2.0, _expectedColor: kRedStencilColor }, // pass -> fail.
+ { secondDepth: 2.0, lastDepth: 0.9, _expectedColor: kGreenStencilColor }, // fail -> pass.
+ ])
+ )
+ .fn(async t => {
+ const { secondDepth, lastDepth, _expectedColor } = t.params;
+
+ const depthSpencilFormat = 'depth24plus-stencil8';
+
+ const baseState = {
+ format: depthSpencilFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'always',
+ stencilReadMask: 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const depthTestState = {
+ format: depthSpencilFormat,
+ depthWriteEnabled: true,
+ depthCompare: 'less',
+ stencilReadMask: 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const testStates = [
+ { state: baseState, color: kBaseColor, depth: 1.0 },
+ { state: depthTestState, color: kRedStencilColor, depth: secondDepth },
+ { state: depthTestState, color: kGreenStencilColor, depth: lastDepth },
+ ];
+
+ t.runDepthStateTest(testStates, _expectedColor);
+ });
+
+// Use a depth value that's not exactly 0.5 because it is exactly between two depth16unorm value and
+// can get rounded either way (and a different way between shaders and clearDepthValue).
+const kMiddleDepthValue = 0.5001;
+
+g.test('depth_compare_func')
+ .desc(
+ `Tests each depth compare function works properly. Clears the depth attachment to various values, and renders a point at depth 0.5 with various depthCompare modes.`
+ )
+ .params(u =>
+ u
+ .combine(
+ 'format',
+ kDepthStencilFormats.filter(format => kTextureFormatInfo[format].depth)
+ )
+ .combineWithParams([
+ { depthCompare: 'never', depthClearValue: 1.0, _expected: backgroundColor },
+ { depthCompare: 'never', depthClearValue: kMiddleDepthValue, _expected: backgroundColor },
+ { depthCompare: 'never', depthClearValue: 0.0, _expected: backgroundColor },
+ { depthCompare: 'less', depthClearValue: 1.0, _expected: triangleColor },
+ { depthCompare: 'less', depthClearValue: kMiddleDepthValue, _expected: backgroundColor },
+ { depthCompare: 'less', depthClearValue: 0.0, _expected: backgroundColor },
+ { depthCompare: 'less-equal', depthClearValue: 1.0, _expected: triangleColor },
+ {
+ depthCompare: 'less-equal',
+ depthClearValue: kMiddleDepthValue,
+ _expected: triangleColor,
+ },
+ { depthCompare: 'less-equal', depthClearValue: 0.0, _expected: backgroundColor },
+ { depthCompare: 'equal', depthClearValue: 1.0, _expected: backgroundColor },
+ { depthCompare: 'equal', depthClearValue: kMiddleDepthValue, _expected: triangleColor },
+ { depthCompare: 'equal', depthClearValue: 0.0, _expected: backgroundColor },
+ { depthCompare: 'not-equal', depthClearValue: 1.0, _expected: triangleColor },
+ {
+ depthCompare: 'not-equal',
+ depthClearValue: kMiddleDepthValue,
+ _expected: backgroundColor,
+ },
+ { depthCompare: 'not-equal', depthClearValue: 0.0, _expected: triangleColor },
+ { depthCompare: 'greater-equal', depthClearValue: 1.0, _expected: backgroundColor },
+ {
+ depthCompare: 'greater-equal',
+ depthClearValue: kMiddleDepthValue,
+ _expected: triangleColor,
+ },
+ { depthCompare: 'greater-equal', depthClearValue: 0.0, _expected: triangleColor },
+ { depthCompare: 'greater', depthClearValue: 1.0, _expected: backgroundColor },
+ { depthCompare: 'greater', depthClearValue: kMiddleDepthValue, _expected: backgroundColor },
+ { depthCompare: 'greater', depthClearValue: 0.0, _expected: triangleColor },
+ { depthCompare: 'always', depthClearValue: 1.0, _expected: triangleColor },
+ { depthCompare: 'always', depthClearValue: kMiddleDepthValue, _expected: triangleColor },
+ { depthCompare: 'always', depthClearValue: 0.0, _expected: triangleColor },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { depthCompare, depthClearValue, _expected, format } = t.params;
+
+ const colorAttachmentFormat = 'rgba8unorm';
+ const colorAttachment = t.device.createTexture({
+ format: colorAttachmentFormat,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const depthTexture = t.device.createTexture({
+ size: { width: 1, height: 1 },
+ format,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ });
+ const depthTextureView = depthTexture.createView();
+
+ const pipelineDescriptor = {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.5, 0.5, ${kMiddleDepthValue}, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: colorAttachmentFormat }],
+ },
+ primitive: { topology: 'point-list' },
+ depthStencil: {
+ depthWriteEnabled: true,
+ depthCompare,
+ format,
+ },
+ };
+ const pipeline = t.device.createRenderPipeline(pipelineDescriptor);
+
+ const encoder = t.device.createCommandEncoder();
+ const depthStencilAttachment = {
+ view: depthTextureView,
+ depthClearValue,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ };
+ if (kTextureFormatInfo[format].stencil) {
+ depthStencilAttachment.stencilClearValue = 0;
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ colorAttachmentFormat,
+ { x: 0, y: 0 },
+ { exp: new Uint8Array(_expected) }
+ );
+ });
+
+g.test('reverse_depth')
+ .desc(
+ `Tests simple rendering with reversed depth buffer, ensures depth test works properly: fragments are in correct order and out of range fragments are clipped.
+ Note that in real use case the depth range remapping is done by the modified projection matrix.
+(see https://developer.nvidia.com/content/depth-precision-visualized).`
+ )
+ .params(u => u.combine('reversed', [false, true]))
+ .fn(async t => {
+ const colorAttachmentFormat = 'rgba8unorm';
+ const colorAttachment = t.device.createTexture({
+ format: colorAttachmentFormat,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const depthBufferFormat = 'depth32float';
+ const depthTexture = t.device.createTexture({
+ size: { width: 1, height: 1 },
+ format: depthBufferFormat,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ });
+ const depthTextureView = depthTexture.createView();
+
+ const pipelineDescriptor = {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ struct Output {
+ @builtin(position) Position : vec4<f32>,
+ @location(0) color : vec4<f32>,
+ };
+
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32,
+ @builtin(instance_index) InstanceIndex : u32) -> Output {
+ // TODO: remove workaround for Tint unary array access broke
+ var zv : array<vec2<f32>, 4> = array<vec2<f32>, 4>(
+ vec2<f32>(0.2, 0.2),
+ vec2<f32>(0.3, 0.3),
+ vec2<f32>(-0.1, -0.1),
+ vec2<f32>(1.1, 1.1));
+ let z : f32 = zv[InstanceIndex].x;
+
+ var output : Output;
+ output.Position = vec4<f32>(0.5, 0.5, z, 1.0);
+ var colors : array<vec4<f32>, 4> = array<vec4<f32>, 4>(
+ vec4<f32>(1.0, 0.0, 0.0, 1.0),
+ vec4<f32>(0.0, 1.0, 0.0, 1.0),
+ vec4<f32>(0.0, 0.0, 1.0, 1.0),
+ vec4<f32>(1.0, 1.0, 1.0, 1.0)
+ );
+ output.color = colors[InstanceIndex];
+ return output;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment fn main(
+ @location(0) color : vec4<f32>
+ ) -> @location(0) vec4<f32> {
+ return color;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: colorAttachmentFormat }],
+ },
+ primitive: { topology: 'point-list' },
+ depthStencil: {
+ depthWriteEnabled: true,
+ depthCompare: t.params.reversed ? 'greater' : 'less',
+ format: depthBufferFormat,
+ },
+ };
+ const pipeline = t.device.createRenderPipeline(pipelineDescriptor);
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: depthTextureView,
+
+ depthClearValue: t.params.reversed ? 0.0 : 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ },
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(1, 4);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ colorAttachmentFormat,
+ { x: 0, y: 0 },
+ {
+ exp: new Uint8Array(
+ t.params.reversed ? [0x00, 0xff, 0x00, 0xff] : [0xff, 0x00, 0x00, 0xff]
+ ),
+ }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js
new file mode 100644
index 0000000000..eff6266bae
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_bias.spec.js
@@ -0,0 +1,327 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests render results with different depth bias values like 'positive', 'negative',
+'slope', 'clamp', etc.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+var QuadAngle;
+
+// Floating point depth buffers use the following formula to calculate bias
+// bias = depthBias * 2 ** (exponent(max z of primitive) - number of bits in mantissa) +
+// slopeScale * maxSlope
+// https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
+// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdSetDepthBias.html
+// https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1516269-setdepthbias
+//
+// To get a final bias of 0.25 for primitives with z = 0.25, we can use
+// depthBias = 0.25 / (2 ** (-2 - 23)) = 8388608.
+(function (QuadAngle) {
+ QuadAngle[(QuadAngle['Flat'] = 0)] = 'Flat';
+ QuadAngle[(QuadAngle['TiltedX'] = 1)] = 'TiltedX';
+})(QuadAngle || (QuadAngle = {}));
+const kPointTwoFiveBiasForPointTwoFiveZOnFloat = 8388608;
+
+class DepthBiasTest extends GPUTest {
+ runDepthBiasTestInternal(
+ depthFormat,
+ { quadAngle, bias, biasSlopeScale, biasClamp, initialDepth }
+ ) {
+ const renderTargetFormat = 'rgba8unorm';
+ const depthFormatInfo = kTextureFormatInfo[depthFormat];
+
+ let vertexShaderCode;
+ switch (quadAngle) {
+ case QuadAngle.Flat:
+ // Draw a square at z = 0.25.
+ vertexShaderCode = `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>( 1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.25, 1.0);
+ }
+ `;
+ break;
+ case QuadAngle.TiltedX:
+ // Draw a square ranging from 0 to 0.5, bottom to top.
+ vertexShaderCode = `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec3<f32>, 6>(
+ vec3<f32>(-1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, -1.0, 0.0),
+ vec3<f32>(-1.0, 1.0, 0.5),
+ vec3<f32>(-1.0, 1.0, 0.5),
+ vec3<f32>( 1.0, -1.0, 0.0),
+ vec3<f32>( 1.0, 1.0, 0.5));
+ return vec4<f32>(pos[VertexIndex], 1.0);
+ }
+ `;
+ break;
+ default:
+ unreachable();
+ }
+
+ const renderTarget = this.device.createTexture({
+ format: renderTargetFormat,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const depthTexture = this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: depthFormat,
+ sampleCount: 1,
+ mipLevelCount: 1,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+
+ const depthStencilAttachment = {
+ view: depthTexture.createView(),
+ depthLoadOp: depthFormatInfo.depth ? 'clear' : undefined,
+ depthStoreOp: depthFormatInfo.depth ? 'store' : undefined,
+ stencilLoadOp: depthFormatInfo.stencil ? 'clear' : undefined,
+ stencilStoreOp: depthFormatInfo.stencil ? 'store' : undefined,
+ depthClearValue: initialDepth,
+ };
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ loadOp: 'load',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+
+ let depthCompare = 'always';
+ if (depthFormat !== 'depth32float') {
+ depthCompare = 'greater';
+ }
+
+ const testState = {
+ format: depthFormat,
+ depthCompare,
+ depthWriteEnabled: true,
+ depthBias: bias,
+ depthBiasSlopeScale: biasSlopeScale,
+ depthBiasClamp: biasClamp,
+ };
+
+ // Draw a square with the given depth state and bias values.
+ const testPipeline = this.createRenderPipelineForTest(vertexShaderCode, testState);
+ pass.setPipeline(testPipeline);
+ pass.draw(6);
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ return { renderTarget, depthTexture };
+ }
+
+ runDepthBiasTest(depthFormat, { quadAngle, bias, biasSlopeScale, biasClamp, _expectedDepth }) {
+ const { renderTarget, depthTexture } = this.runDepthBiasTestInternal(depthFormat, {
+ quadAngle,
+ bias,
+ biasSlopeScale,
+ biasClamp,
+ initialDepth: 0,
+ });
+
+ const expColor = { Depth: _expectedDepth };
+ const expTexelView = TexelView.fromTexelsAsColors(depthFormat, coords => expColor);
+
+ const result = textureContentIsOKByT2B(
+ this,
+ { texture: depthTexture },
+ [1, 1],
+ { expTexelView },
+ { maxDiffULPsForFloatFormat: 1 }
+ );
+
+ this.eventualExpectOK(result);
+ this.trackForCleanup(renderTarget);
+ this.trackForCleanup(depthTexture);
+ }
+
+ runDepthBiasTestFor24BitFormat(
+ depthFormat,
+ { quadAngle, bias, biasSlopeScale, biasClamp, _expectedColor }
+ ) {
+ const { renderTarget, depthTexture } = this.runDepthBiasTestInternal(depthFormat, {
+ quadAngle,
+ bias,
+ biasSlopeScale,
+ biasClamp,
+ initialDepth: 0.4,
+ });
+
+ const renderTargetFormat = 'rgba8unorm';
+ const expColor = {
+ R: _expectedColor[0],
+ G: _expectedColor[1],
+ B: _expectedColor[2],
+ A: _expectedColor[3],
+ };
+ const expTexelView = TexelView.fromTexelsAsColors(renderTargetFormat, coords => expColor);
+
+ const result = textureContentIsOKByT2B(
+ this,
+ { texture: renderTarget },
+ [1, 1],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ this.eventualExpectOK(result);
+ this.trackForCleanup(renderTarget);
+ this.trackForCleanup(depthTexture);
+ }
+
+ createRenderPipelineForTest(vertex, depthStencil) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: vertex,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ targets: [{ format: 'rgba8unorm' }],
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ depthStencil,
+ });
+ }
+}
+
+export const g = makeTestGroup(DepthBiasTest);
+
+g.test('depth_bias')
+ .desc(
+ `
+ Tests that a square with different depth bias values like 'positive', 'negative',
+ 'slope', 'clamp', etc. is drawn as expected.
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: kPointTwoFiveBiasForPointTwoFiveZOnFloat,
+ biasSlopeScale: 0,
+ biasClamp: 0,
+ _expectedDepth: 0.5,
+ },
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: kPointTwoFiveBiasForPointTwoFiveZOnFloat,
+ biasSlopeScale: 0,
+ biasClamp: 0.125,
+ _expectedDepth: 0.375,
+ },
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: -kPointTwoFiveBiasForPointTwoFiveZOnFloat,
+ biasSlopeScale: 0,
+ biasClamp: 0.125,
+ _expectedDepth: 0,
+ },
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: -kPointTwoFiveBiasForPointTwoFiveZOnFloat,
+ biasSlopeScale: 0,
+ biasClamp: -0.125,
+ _expectedDepth: 0.125,
+ },
+ {
+ quadAngle: QuadAngle.TiltedX,
+ bias: 0,
+ biasSlopeScale: 0,
+ biasClamp: 0,
+ _expectedDepth: 0.25,
+ },
+ {
+ quadAngle: QuadAngle.TiltedX,
+ bias: 0,
+ biasSlopeScale: 1,
+ biasClamp: 0,
+ _expectedDepth: 0.75,
+ },
+ {
+ quadAngle: QuadAngle.TiltedX,
+ bias: 0,
+ biasSlopeScale: -0.5,
+ biasClamp: 0,
+ _expectedDepth: 0,
+ },
+ ])
+ )
+ .fn(async t => {
+ t.runDepthBiasTest('depth32float', t.params);
+ });
+
+g.test('depth_bias_24bit_format')
+ .desc(
+ `
+ Tests that a square with different depth bias values like 'positive', 'negative',
+ 'slope', 'clamp', etc. is drawn as expected with 24 bit depth format.
+
+ TODO: Enhance these tests by reading back the depth (emulating the copy using texture sampling)
+ and checking the result directly, like the non-24-bit depth tests, instead of just relying on
+ whether the depth test passes or fails.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', ['depth24plus', 'depth24plus-stencil8'])
+ .combineWithParams([
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: 0.25 * (1 << 25),
+ biasSlopeScale: 0,
+ biasClamp: 0,
+ _expectedColor: new Float32Array([1.0, 0.0, 0.0, 1.0]),
+ },
+ {
+ quadAngle: QuadAngle.TiltedX,
+ bias: 0.25 * (1 << 25),
+ biasSlopeScale: 1,
+ biasClamp: 0,
+ _expectedColor: new Float32Array([1.0, 0.0, 0.0, 1.0]),
+ },
+ {
+ quadAngle: QuadAngle.Flat,
+ bias: 0.25 * (1 << 25),
+ biasSlopeScale: 0,
+ biasClamp: 0.1,
+ _expectedColor: new Float32Array([0.0, 0.0, 0.0, 0.0]),
+ },
+ ])
+ )
+ .fn(async t => {
+ const { format } = t.params;
+ t.runDepthBiasTestFor24BitFormat(format, t.params);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js
new file mode 100644
index 0000000000..3e40812d28
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/depth_clip_clamp.spec.js
@@ -0,0 +1,524 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for depth clipping, depth clamping (at various points in the pipeline), and maybe extended
+depth ranges as well.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kDepthStencilFormats, kTextureFormatInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsBetween, checkElementsPassPredicate } from '../../../util/check_contents.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('depth_clamp_and_clip')
+ .desc(
+ `
+Depth written to the depth attachment should always be in the range of the viewport depth,
+even if it was written by the fragment shader (using frag_depth). If depth clipping is enabled,
+primitives should be clipped to the viewport depth before rasterization; if not, these fragments
+should be rasterized, and the fragment shader should receive out-of-viewport position.z values.
+
+To test this, render NxN points, with N vertex depth values, by (if writeDepth=true) N
+frag_depth values with the viewport depth set to [0.25,0.75].
+
+While rendering, check the fragment input position.z has the expected value (for all fragments that
+were produced by the rasterizer) by writing the diff to a storage buffer, which is later checked to
+be all (near) 0.
+
+Then, run another pass (which outputs every point at z=0.5 to avoid clipping) to verify the depth
+buffer contents by outputting the expected depth with depthCompare:'not-equal': any fragments that
+have unexpected values then get drawn to the color buffer, which is later checked to be empty.`
+ )
+ .params(u =>
+ u //
+ .combine('format', kDepthStencilFormats)
+ .filter(p => kTextureFormatInfo[p.format].depth)
+ .combine('unclippedDepth', [undefined, false, true])
+ .combine('writeDepth', [false, true])
+ .combine('multisampled', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+
+ t.selectDeviceOrSkipTestCase([
+ t.params.unclippedDepth ? 'depth-clip-control' : undefined,
+ info.feature,
+ ]);
+ })
+ .fn(async t => {
+ const { format, unclippedDepth, writeDepth, multisampled } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ /** Number of depth values to test for both vertex output and frag_depth output. */
+ const kNumDepthValues = 8;
+ /** Test every combination of vertex output and frag_depth output. */
+ const kNumTestPoints = kNumDepthValues * kNumDepthValues;
+ const kViewportMinDepth = 0.25;
+ const kViewportMaxDepth = 0.75;
+
+ const shaderSource = `
+ // Test depths, with viewport range corresponding to [0,1].
+ var<private> kDepths: array<f32, ${kNumDepthValues}> = array<f32, ${kNumDepthValues}>(
+ -1.0, -0.5, 0.0, 0.25, 0.75, 1.0, 1.5, 2.0);
+
+ const vpMin: f32 = ${kViewportMinDepth};
+ const vpMax: f32 = ${kViewportMaxDepth};
+
+ // Draw the points in a straight horizontal row, one per pixel.
+ fn vertexX(idx: u32) -> f32 {
+ return (f32(idx) + 0.5) * 2.0 / ${kNumTestPoints}.0 - 1.0;
+ }
+
+ // Test vertex shader's position.z output.
+ // Here, the viewport range corresponds to position.z in [0,1].
+ fn vertexZ(idx: u32) -> f32 {
+ return kDepths[idx / ${kNumDepthValues}u];
+ }
+
+ // Test fragment shader's expected position.z input.
+ // Here, the viewport range corresponds to position.z in [vpMin,vpMax], but
+ // unclipped values extend beyond that range.
+ fn expectedFragPosZ(idx: u32) -> f32 {
+ return vpMin + vertexZ(idx) * (vpMax - vpMin);
+ }
+
+ //////// "Test" entry points
+
+ struct VFTest {
+ @builtin(position) pos: vec4<f32>,
+ @location(0) @interpolate(flat) vertexIndex: u32,
+ };
+
+ @vertex
+ fn vtest(@builtin(vertex_index) idx: u32) -> VFTest {
+ var vf: VFTest;
+ vf.pos = vec4<f32>(vertexX(idx), 0.0, vertexZ(idx), 1.0);
+ vf.vertexIndex = idx;
+ return vf;
+ }
+
+ struct Output {
+ // Each fragment (that didn't get clipped) writes into one element of this output.
+ // (Anything that doesn't get written is already zero.)
+ fragInputZDiff: array<f32, ${kNumTestPoints}>
+ };
+ @group(0) @binding(0) var <storage, read_write> output: Output;
+
+ fn checkZ(vf: VFTest) {
+ output.fragInputZDiff[vf.vertexIndex] = vf.pos.z - expectedFragPosZ(vf.vertexIndex);
+ }
+
+ @fragment
+ fn ftest_WriteDepth(vf: VFTest) -> @builtin(frag_depth) f32 {
+ checkZ(vf);
+ return kDepths[vf.vertexIndex % ${kNumDepthValues}u];
+ }
+
+ @fragment
+ fn ftest_NoWriteDepth(vf: VFTest) {
+ checkZ(vf);
+ }
+
+ //////// "Check" entry points
+
+ struct VFCheck {
+ @builtin(position) pos: vec4<f32>,
+ @location(0) @interpolate(flat) vertexIndex: u32,
+ };
+
+ @vertex
+ fn vcheck(@builtin(vertex_index) idx: u32) -> VFCheck {
+ var vf: VFCheck;
+ // Depth=0.5 because we want to render every point, not get clipped.
+ vf.pos = vec4<f32>(vertexX(idx), 0.0, 0.5, 1.0);
+ vf.vertexIndex = idx;
+ return vf;
+ }
+
+ struct FCheck {
+ @builtin(frag_depth) depth: f32,
+ @location(0) color: f32,
+ };
+
+ @fragment
+ fn fcheck(vf: VFCheck) -> FCheck {
+ let vertZ = vertexZ(vf.vertexIndex);
+ let outOfRange = vertZ < 0.0 || vertZ > 1.0;
+ let expFragPosZ = expectedFragPosZ(vf.vertexIndex);
+
+ let writtenDepth = kDepths[vf.vertexIndex % ${kNumDepthValues}u];
+
+ let expectedDepthWriteInput = ${writeDepth ? 'writtenDepth' : 'expFragPosZ'};
+ var expectedDepthBufferValue = clamp(expectedDepthWriteInput, vpMin, vpMax);
+ if (${!unclippedDepth} && outOfRange) {
+ // Test fragment should have been clipped; expect the depth attachment to
+ // have its clear value (0.5).
+ expectedDepthBufferValue = 0.5;
+ }
+
+ var f: FCheck;
+ f.depth = expectedDepthBufferValue;
+ f.color = 1.0; // Color written if the resulting depth is unexpected.
+ return f;
+ }
+ `;
+ const module = t.device.createShaderModule({ code: shaderSource });
+
+ // Draw points at different vertex depths and fragment depths into the depth attachment,
+ // with a viewport of [0.25,0.75].
+ const testPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module, entryPoint: 'vtest' },
+ primitive: {
+ topology: 'point-list',
+ unclippedDepth,
+ },
+ depthStencil: { format, depthWriteEnabled: true },
+ multisample: multisampled ? { count: 4 } : undefined,
+ fragment: {
+ module,
+ entryPoint: writeDepth ? 'ftest_WriteDepth' : 'ftest_NoWriteDepth',
+ targets: [],
+ },
+ });
+
+ // Use depth comparison to check that the depth attachment now has the expected values.
+ const checkPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module, entryPoint: 'vcheck' },
+ primitive: { topology: 'point-list' },
+ depthStencil: {
+ format,
+ // NOTE: This check is probably very susceptible to floating point error. If it fails, maybe
+ // replace it with two checks (less + greater) with an epsilon applied in the check shader?
+ depthCompare: 'not-equal', // Expect every depth value to be exactly equal.
+ depthWriteEnabled: true, // If the check failed, overwrite with the expected result.
+ },
+ multisample: multisampled ? { count: 4 } : undefined,
+ fragment: { module, entryPoint: 'fcheck', targets: [{ format: 'r8unorm' }] },
+ });
+
+ const dsTexture = t.device.createTexture({
+ format,
+ size: [kNumTestPoints],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ sampleCount: multisampled ? 4 : 1,
+ });
+ const dsTextureView = dsTexture.createView();
+
+ const checkTextureDesc = {
+ format: 'r8unorm',
+ size: [kNumTestPoints],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ };
+ const checkTexture = t.device.createTexture(checkTextureDesc);
+ const checkTextureView = checkTexture.createView();
+ const checkTextureMSView = multisampled
+ ? t.device.createTexture({ ...checkTextureDesc, sampleCount: 4 }).createView()
+ : undefined;
+
+ const dsActual =
+ !multisampled && info.bytesPerBlock
+ ? t.device.createBuffer({
+ size: kNumTestPoints * info.bytesPerBlock,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ })
+ : undefined;
+ const dsExpected =
+ !multisampled && info.bytesPerBlock
+ ? t.device.createBuffer({
+ size: kNumTestPoints * info.bytesPerBlock,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ })
+ : undefined;
+ const checkBuffer = t.device.createBuffer({
+ size: kNumTestPoints,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+
+ const fragInputZFailedBuffer = t.device.createBuffer({
+ size: 4 * kNumTestPoints,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ const testBindGroup = t.device.createBindGroup({
+ layout: testPipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: fragInputZFailedBuffer } }],
+ });
+
+ const enc = t.device.createCommandEncoder();
+ {
+ const pass = enc.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: dsTextureView,
+ depthClearValue: 0.5, // Will see this depth value if the fragment was clipped.
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilClearValue: info.stencil ? 0 : undefined,
+ stencilLoadOp: info.stencil ? 'clear' : undefined,
+ stencilStoreOp: info.stencil ? 'discard' : undefined,
+ },
+ });
+ pass.setPipeline(testPipeline);
+ pass.setBindGroup(0, testBindGroup);
+ pass.setViewport(0, 0, kNumTestPoints, 1, kViewportMinDepth, kViewportMaxDepth);
+ pass.draw(kNumTestPoints);
+ pass.end();
+ }
+ if (dsActual) {
+ enc.copyTextureToBuffer({ texture: dsTexture }, { buffer: dsActual }, [kNumTestPoints]);
+ }
+ {
+ const clearValue = [0, 0, 0, 0]; // Will see this color if the check passed.
+ const pass = enc.beginRenderPass({
+ colorAttachments: [
+ checkTextureMSView
+ ? {
+ view: checkTextureMSView,
+ resolveTarget: checkTextureView,
+ clearValue,
+ loadOp: 'clear',
+ storeOp: 'discard',
+ }
+ : { view: checkTextureView, clearValue, loadOp: 'clear', storeOp: 'store' },
+ ],
+
+ depthStencilAttachment: {
+ view: dsTextureView,
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilClearValue: info.stencil ? 0 : undefined,
+ stencilLoadOp: info.stencil ? 'clear' : undefined,
+ stencilStoreOp: info.stencil ? 'discard' : undefined,
+ },
+ });
+ pass.setPipeline(checkPipeline);
+ pass.setViewport(0, 0, kNumTestPoints, 1, 0.0, 1.0);
+ pass.draw(kNumTestPoints);
+ pass.end();
+ }
+ enc.copyTextureToBuffer({ texture: checkTexture }, { buffer: checkBuffer }, [kNumTestPoints]);
+ if (dsExpected) {
+ enc.copyTextureToBuffer({ texture: dsTexture }, { buffer: dsExpected }, [kNumTestPoints]);
+ }
+ t.device.queue.submit([enc.finish()]);
+
+ t.expectGPUBufferValuesPassCheck(
+ fragInputZFailedBuffer,
+ a => checkElementsBetween(a, [() => -1e-5, () => 1e-5]),
+ { type: Float32Array, typedLength: kNumTestPoints }
+ );
+
+ const kCheckPassedValue = 0;
+ const predicatePrinter = [
+ { leftHeader: 'expected ==', getValueForCell: index => kCheckPassedValue },
+ ];
+
+ if (dsActual && dsExpected && format === 'depth32float') {
+ await Promise.all([dsActual.mapAsync(GPUMapMode.READ), dsExpected.mapAsync(GPUMapMode.READ)]);
+ const act = new Float32Array(dsActual.getMappedRange());
+ const exp = new Float32Array(dsExpected.getMappedRange());
+ predicatePrinter.push(
+ { leftHeader: 'act ==', getValueForCell: index => act[index].toFixed(2) },
+ { leftHeader: 'exp ==', getValueForCell: index => exp[index].toFixed(2) }
+ );
+ }
+ t.expectGPUBufferValuesPassCheck(
+ checkBuffer,
+ a =>
+ checkElementsPassPredicate(a, (index, value) => value === kCheckPassedValue, {
+ predicatePrinter,
+ }),
+ { type: Uint8Array, typedLength: kNumTestPoints, method: 'map' }
+ );
+ });
+
+g.test('depth_test_input_clamped')
+ .desc(
+ `
+Input to the depth test should always be in the range of viewport depth, even if it was written by
+the fragment shader (using frag_depth).
+
+To test this, first initialize the depth buffer with N expected values (by writing frag_depth, with
+the default viewport). These expected values are clamped by the shader to [0.25, 0.75].
+
+Then, run another pass with the viewport depth set to [0.25,0.75], and output various (unclamped)
+frag_depth values from its fragment shader with depthCompare:'not-equal'. These should get clamped;
+any fragments that have unexpected values then get drawn to the color buffer, which is later checked
+to be empty.`
+ )
+ .params(u =>
+ u //
+ .combine('format', kDepthStencilFormats)
+ .filter(p => kTextureFormatInfo[p.format].depth)
+ .combine('unclippedDepth', [false, true])
+ .combine('multisampled', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+
+ t.selectDeviceOrSkipTestCase([
+ t.params.unclippedDepth ? 'depth-clip-control' : undefined,
+ info.feature,
+ ]);
+ })
+ .fn(async t => {
+ const { format, unclippedDepth, multisampled } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const kNumDepthValues = 8;
+ const kViewportMinDepth = 0.25;
+ const kViewportMaxDepth = 0.75;
+
+ const shaderSource = `
+ // Test depths, with viewport range corresponding to [0,1].
+ var<private> kDepths: array<f32, ${kNumDepthValues}> = array<f32, ${kNumDepthValues}>(
+ -1.0, -0.5, 0.0, 0.25, 0.75, 1.0, 1.5, 2.0);
+
+ const vpMin: f32 = ${kViewportMinDepth};
+ const vpMax: f32 = ${kViewportMaxDepth};
+
+ // Draw the points in a straight horizontal row, one per pixel.
+ fn vertexX(idx: u32) -> f32 {
+ return (f32(idx) + 0.5) * 2.0 / ${kNumDepthValues}.0 - 1.0;
+ }
+
+ struct VF {
+ @builtin(position) pos: vec4<f32>,
+ @location(0) @interpolate(flat) vertexIndex: u32,
+ };
+
+ @vertex
+ fn vmain(@builtin(vertex_index) idx: u32) -> VF {
+ var vf: VF;
+ // Depth=0.5 because we want to render every point, not get clipped.
+ vf.pos = vec4<f32>(vertexX(idx), 0.0, 0.5, 1.0);
+ vf.vertexIndex = idx;
+ return vf;
+ }
+
+ @fragment
+ fn finit(vf: VF) -> @builtin(frag_depth) f32 {
+ // Expected values of the ftest pipeline.
+ return clamp(kDepths[vf.vertexIndex], vpMin, vpMax);
+ }
+
+ struct FTest {
+ @builtin(frag_depth) depth: f32,
+ @location(0) color: f32,
+ };
+
+ @fragment
+ fn ftest(vf: VF) -> FTest {
+ var f: FTest;
+ f.depth = kDepths[vf.vertexIndex]; // Should get clamped to the viewport.
+ f.color = 1.0; // Color written if the resulting depth is unexpected.
+ return f;
+ }
+ `;
+
+ const module = t.device.createShaderModule({ code: shaderSource });
+
+ // Initialize depth attachment with expected values, in [0.25,0.75].
+ const initPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module, entryPoint: 'vmain' },
+ primitive: { topology: 'point-list' },
+ depthStencil: { format, depthWriteEnabled: true },
+ multisample: multisampled ? { count: 4 } : undefined,
+ fragment: { module, entryPoint: 'finit', targets: [] },
+ });
+
+ // With a viewport set to [0.25,0.75], output values in [0.0,1.0] and check they're clamped
+ // before the depth test, regardless of whether unclippedDepth is enabled.
+ const testPipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module, entryPoint: 'vmain' },
+ primitive: {
+ topology: 'point-list',
+ unclippedDepth,
+ },
+ depthStencil: { format, depthCompare: 'not-equal' },
+ multisample: multisampled ? { count: 4 } : undefined,
+ fragment: { module, entryPoint: 'ftest', targets: [{ format: 'r8unorm' }] },
+ });
+
+ const dsTexture = t.device.createTexture({
+ format,
+ size: [kNumDepthValues],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ sampleCount: multisampled ? 4 : 1,
+ });
+ const dsTextureView = dsTexture.createView();
+
+ const testTextureDesc = {
+ format: 'r8unorm',
+ size: [kNumDepthValues],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ };
+ const testTexture = t.device.createTexture(testTextureDesc);
+ const testTextureView = testTexture.createView();
+ const testTextureMSView = multisampled
+ ? t.device.createTexture({ ...testTextureDesc, sampleCount: 4 }).createView()
+ : undefined;
+
+ const resultBuffer = t.device.createBuffer({
+ size: kNumDepthValues,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+
+ const enc = t.device.createCommandEncoder();
+ {
+ const pass = enc.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: dsTextureView,
+ depthClearValue: 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilClearValue: info.stencil ? 0 : undefined,
+ stencilLoadOp: info.stencil ? 'clear' : undefined,
+ stencilStoreOp: info.stencil ? 'discard' : undefined,
+ },
+ });
+ pass.setPipeline(initPipeline);
+ pass.draw(kNumDepthValues);
+ pass.end();
+ }
+ {
+ const clearValue = [0, 0, 0, 0]; // Will see this color if the test passed.
+ const pass = enc.beginRenderPass({
+ colorAttachments: [
+ testTextureMSView
+ ? {
+ view: testTextureMSView,
+ resolveTarget: testTextureView,
+ clearValue,
+ loadOp: 'clear',
+ storeOp: 'discard',
+ }
+ : { view: testTextureView, clearValue, loadOp: 'clear', storeOp: 'store' },
+ ],
+
+ depthStencilAttachment: {
+ view: dsTextureView,
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilClearValue: info.stencil ? 0 : undefined,
+ stencilLoadOp: info.stencil ? 'clear' : undefined,
+ stencilStoreOp: info.stencil ? 'discard' : undefined,
+ },
+ });
+ pass.setPipeline(testPipeline);
+ pass.setViewport(0, 0, kNumDepthValues, 1, kViewportMinDepth, kViewportMaxDepth);
+ pass.draw(kNumDepthValues);
+ pass.end();
+ }
+ enc.copyTextureToBuffer({ texture: testTexture }, { buffer: resultBuffer }, [kNumDepthValues]);
+ t.device.queue.submit([enc.finish()]);
+
+ t.expectGPUBufferValuesEqual(resultBuffer, new Uint8Array(kNumDepthValues), 0, {
+ method: 'map',
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/draw.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/draw.spec.js
new file mode 100644
index 0000000000..caca453e9d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/draw.spec.js
@@ -0,0 +1,745 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for the general aspects of draw/drawIndexed/drawIndirect/drawIndexedIndirect.
+
+Primitive topology tested in api/operation/render_pipeline/primitive_topology.spec.ts.
+Index format tested in api/operation/command_buffer/render/state_tracking.spec.ts.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+class DrawTest extends GPUTest {
+ checkTriangleDraw(opts) {
+ // Set fallbacks when parameters are undefined in order to calculate the expected values.
+ const defaulted = {
+ firstIndex: opts.firstIndex ?? 0,
+ count: opts.count,
+ firstInstance: opts.firstInstance ?? 0,
+ instanceCount: opts.instanceCount ?? 1,
+ indexed: opts.indexed,
+ indirect: opts.indirect,
+ vertexBufferOffset: opts.vertexBufferOffset,
+ indexBufferOffset: opts.indexBufferOffset ?? 0,
+ baseVertex: opts.baseVertex ?? 0,
+ };
+
+ const renderTargetSize = [72, 36];
+
+ // The test will split up the render target into a grid where triangles of
+ // increasing primitive id will be placed along the X axis, and triangles
+ // of increasing instance id will be placed along the Y axis. The size of the
+ // grid is based on the max primitive id and instance id used.
+ const numX = 6;
+ const numY = 6;
+ const tileSizeX = renderTargetSize[0] / numX;
+ const tileSizeY = renderTargetSize[1] / numY;
+
+ // |\
+ // | \
+ // |______\
+ // Unit triangle shaped like this. 0-1 Y-down.
+ const triangleVertices = [0.0, 0.0, 0.0, 1.0, 1.0, 1.0];
+
+ const renderTarget = this.device.createTexture({
+ size: renderTargetSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ format: 'rgba8unorm',
+ });
+
+ const vertexModule = this.device.createShaderModule({
+ code: `
+struct Inputs {
+ @builtin(vertex_index) vertex_index : u32,
+ @builtin(instance_index) instance_id : u32,
+ @location(0) vertexPosition : vec2<f32>,
+};
+
+@vertex fn vert_main(input : Inputs
+ ) -> @builtin(position) vec4<f32> {
+ // 3u is the number of points in a triangle to convert from index
+ // to id.
+ var vertex_id : u32 = input.vertex_index / 3u;
+
+ var x : f32 = (input.vertexPosition.x + f32(vertex_id)) / ${numX}.0;
+ var y : f32 = (input.vertexPosition.y + f32(input.instance_id)) / ${numY}.0;
+
+ // (0,1) y-down space to (-1,1) y-up NDC
+ x = 2.0 * x - 1.0;
+ y = -2.0 * y + 1.0;
+ return vec4<f32>(x, y, 0.0, 1.0);
+}
+`,
+ });
+
+ const fragmentModule = this.device.createShaderModule({
+ code: `
+struct Output {
+ value : u32
+};
+
+@group(0) @binding(0) var<storage, read_write> output : Output;
+
+@fragment fn frag_main() -> @location(0) vec4<f32> {
+ output.value = 1u;
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+}
+`,
+ });
+
+ const pipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: vertexModule,
+ entryPoint: 'vert_main',
+ buffers: [
+ {
+ attributes: [
+ {
+ shaderLocation: 0,
+ format: 'float32x2',
+ offset: 0,
+ },
+ ],
+
+ arrayStride: 2 * Float32Array.BYTES_PER_ELEMENT,
+ },
+ ],
+ },
+ fragment: {
+ module: fragmentModule,
+ entryPoint: 'frag_main',
+ targets: [
+ {
+ format: 'rgba8unorm',
+ },
+ ],
+ },
+ });
+
+ const resultBuffer = this.device.createBuffer({
+ size: Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ const resultBindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: resultBuffer,
+ },
+ },
+ ],
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ renderPass.setPipeline(pipeline);
+ renderPass.setBindGroup(0, resultBindGroup);
+
+ if (defaulted.indexed) {
+ // INDEXED DRAW
+ assert(defaulted.baseVertex !== undefined);
+ assert(defaulted.indexBufferOffset !== undefined);
+
+ renderPass.setIndexBuffer(
+ this.makeBufferWithContents(
+ new Uint32Array([
+ // Offset the index buffer contents by empty data.
+ ...new Array(defaulted.indexBufferOffset / Uint32Array.BYTES_PER_ELEMENT),
+
+ 0,
+ 1,
+ 2, //
+ 3,
+ 4,
+ 5, //
+ 6,
+ 7,
+ 8, //
+ ]),
+ GPUBufferUsage.INDEX
+ ),
+
+ 'uint32',
+ defaulted.indexBufferOffset
+ );
+
+ renderPass.setVertexBuffer(
+ 0,
+ this.makeBufferWithContents(
+ new Float32Array([
+ // Offset the vertex buffer contents by empty data.
+ ...new Array(defaulted.vertexBufferOffset / Float32Array.BYTES_PER_ELEMENT),
+
+ // selected with base_vertex=0
+ // count=6
+ ...triangleVertices, // | count=6;first=3
+ ...triangleVertices, // | |
+ ...triangleVertices, // |
+
+ // selected with base_vertex=9
+ // count=6
+ ...triangleVertices, // | count=6;first=3
+ ...triangleVertices, // | |
+ ...triangleVertices, // |
+ ]),
+ GPUBufferUsage.VERTEX
+ ),
+
+ defaulted.vertexBufferOffset
+ );
+
+ if (defaulted.indirect) {
+ const args = [
+ defaulted.count,
+ defaulted.instanceCount,
+ defaulted.firstIndex,
+ defaulted.baseVertex,
+ defaulted.firstInstance,
+ ];
+
+ renderPass.drawIndexedIndirect(
+ this.makeBufferWithContents(new Uint32Array(args), GPUBufferUsage.INDIRECT),
+ 0
+ );
+ } else {
+ const args = [
+ opts.count,
+ opts.instanceCount,
+ opts.firstIndex,
+ opts.baseVertex,
+ opts.firstInstance,
+ ];
+
+ renderPass.drawIndexed.apply(renderPass, [...args]);
+ }
+ } else {
+ // NON-INDEXED DRAW
+ renderPass.setVertexBuffer(
+ 0,
+ this.makeBufferWithContents(
+ new Float32Array([
+ // Offset the vertex buffer contents by empty data.
+ ...new Array(defaulted.vertexBufferOffset / Float32Array.BYTES_PER_ELEMENT),
+
+ // count=6
+ ...triangleVertices, // | count=6;first=3
+ ...triangleVertices, // | |
+ ...triangleVertices, // |
+ ]),
+ GPUBufferUsage.VERTEX
+ ),
+
+ defaulted.vertexBufferOffset
+ );
+
+ if (defaulted.indirect) {
+ const args = [
+ defaulted.count,
+ defaulted.instanceCount,
+ defaulted.firstIndex,
+ defaulted.firstInstance,
+ ];
+
+ renderPass.drawIndirect(
+ this.makeBufferWithContents(new Uint32Array(args), GPUBufferUsage.INDIRECT),
+ 0
+ );
+ } else {
+ const args = [opts.count, opts.instanceCount, opts.firstIndex, opts.firstInstance];
+ renderPass.draw.apply(renderPass, [...args]);
+ }
+ }
+
+ renderPass.end();
+ this.queue.submit([commandEncoder.finish()]);
+
+ const green = new Uint8Array([0, 255, 0, 255]);
+ const transparentBlack = new Uint8Array([0, 0, 0, 0]);
+
+ const didDraw = defaulted.count && defaulted.instanceCount;
+
+ this.expectGPUBufferValuesEqual(resultBuffer, new Uint32Array([didDraw ? 1 : 0]));
+
+ const baseVertexCount = defaulted.baseVertex ?? 0;
+ for (let primitiveId = 0; primitiveId < numX; ++primitiveId) {
+ for (let instanceId = 0; instanceId < numY; ++instanceId) {
+ let expectedColor = didDraw ? green : transparentBlack;
+ if (
+ primitiveId * 3 < defaulted.firstIndex + baseVertexCount ||
+ primitiveId * 3 >= defaulted.firstIndex + baseVertexCount + defaulted.count
+ ) {
+ expectedColor = transparentBlack;
+ }
+
+ if (
+ instanceId < defaulted.firstInstance ||
+ instanceId >= defaulted.firstInstance + defaulted.instanceCount
+ ) {
+ expectedColor = transparentBlack;
+ }
+
+ this.expectSinglePixelIn2DTexture(
+ renderTarget,
+ 'rgba8unorm',
+ {
+ x: (1 / 3 + primitiveId) * tileSizeX,
+ y: (2 / 3 + instanceId) * tileSizeY,
+ },
+ {
+ exp: expectedColor,
+ }
+ );
+ }
+ }
+ }
+}
+
+export const g = makeTestGroup(DrawTest);
+
+g.test('arguments')
+ .desc(
+ `Test that draw arguments are passed correctly by drawing triangles in a grid.
+Horizontally across the texture are triangles with increasing "primitive id".
+Vertically down the screen are triangles with increasing instance id.
+Increasing the |first| param should skip some of the beginning triangles on the horizontal axis.
+Increasing the |first_instance| param should skip of the beginning triangles on the vertical axis.
+The vertex buffer contains two sets of disjoint triangles, and base_vertex is used to select the second set.
+The test checks that the center of all of the expected triangles is drawn, and the others are empty.
+The fragment shader also writes out to a storage buffer. If the draw is zero-sized, check that no value is written.
+
+Params:
+ - first= {0, 3} - either the firstVertex or firstIndex
+ - count= {0, 3, 6} - either the vertexCount or indexCount
+ - first_instance= {0, 2}
+ - instance_count= {0, 1, 4}
+ - indexed= {true, false}
+ - indirect= {true, false}
+ - vertex_buffer_offset= {0, 32}
+ - index_buffer_offset= {0, 16} - only for indexed draws
+ - base_vertex= {0, 9} - only for indexed draws
+ `
+ )
+ .params(u =>
+ u
+ .combine('first', [0, 3])
+ .combine('count', [0, 3, 6])
+ .combine('first_instance', [0, 2])
+ .combine('instance_count', [0, 1, 4])
+ .combine('indexed', [false, true])
+ .combine('indirect', [false, true])
+ .combine('vertex_buffer_offset', [0, 32])
+ .expand('index_buffer_offset', p => (p.indexed ? [0, 16] : [undefined]))
+ .expand('base_vertex', p => (p.indexed ? [0, 9] : [undefined]))
+ )
+ .beforeAllSubcases(t => {
+ if (t.params.first_instance > 0 && t.params.indirect) {
+ t.selectDeviceOrSkipTestCase('indirect-first-instance');
+ }
+ })
+ .fn(async t => {
+ t.checkTriangleDraw({
+ firstIndex: t.params.first,
+ count: t.params.count,
+ firstInstance: t.params.first_instance,
+ instanceCount: t.params.instance_count,
+ indexed: t.params.indexed,
+ indirect: t.params.indirect,
+ vertexBufferOffset: t.params.vertex_buffer_offset,
+ indexBufferOffset: t.params.index_buffer_offset,
+ baseVertex: t.params.base_vertex,
+ });
+ });
+
+g.test('default_arguments')
+ .desc(
+ `
+ Test that defaults arguments are passed correctly by drawing triangles in a grid when they are not
+ defined. This test is written based on the 'arguments' with 'undefined' value in the parameters.
+ - mode= {draw, drawIndexed}
+ - arg= {instance_count, first_index, first_instance, base_vertex}
+ `
+ )
+ .params(u =>
+ u
+ .combine('mode', ['draw', 'drawIndexed'])
+ .beginSubcases()
+ .combine('instance_count', [undefined, 4])
+ .combine('first_index', [undefined, 3])
+ .combine('first_instance', [undefined, 2])
+ .expand('base_vertex', p => (p.mode === 'drawIndexed' ? [undefined, 9] : [undefined]))
+ )
+ .fn(async t => {
+ const kVertexCount = 3;
+ const kVertexBufferOffset = 32;
+ const kIndexBufferOffset = 16;
+
+ t.checkTriangleDraw({
+ firstIndex: t.params.first_index,
+ count: kVertexCount,
+ firstInstance: t.params.first_instance,
+ instanceCount: t.params.instance_count,
+ indexed: t.params.mode === 'drawIndexed',
+ indirect: false, // indirect
+ vertexBufferOffset: kVertexBufferOffset,
+ indexBufferOffset: kIndexBufferOffset,
+ baseVertex: t.params.base_vertex,
+ });
+ });
+
+g.test('vertex_attributes,basic')
+ .desc(
+ `Test basic fetching of vertex attributes.
+ Each vertex attribute is a single value and written out into a storage buffer.
+ Tests that vertices with offsets/strides for instanced/non-instanced attributes are
+ fetched correctly. Not all vertex formats are tested.
+
+ Params:
+ - vertex_attribute_count= {1, 4, 8, 16}
+ - vertex_buffer_count={1, 4, 8} - where # attributes is > 0
+ - vertex_format={uint32, float32}
+ - step_mode= {undefined, vertex, instance, mixed} - where mixed only applies for vertex_buffer_count > 1
+ `
+ )
+ .params(u =>
+ u
+ .combine('vertex_attribute_count', [1, 4, 8, 16])
+ .combine('vertex_buffer_count', [1, 4, 8])
+ .combine('vertex_format', ['uint32', 'float32'])
+ .combine('step_mode', [undefined, 'vertex', 'instance', 'mixed'])
+ .unless(p => p.vertex_attribute_count < p.vertex_buffer_count)
+ .unless(p => p.step_mode === 'mixed' && p.vertex_buffer_count <= 1)
+ )
+ .fn(t => {
+ const vertexCount = 4;
+ const instanceCount = 4;
+
+ const attributesPerVertexBuffer =
+ t.params.vertex_attribute_count / t.params.vertex_buffer_count;
+ assert(Math.round(attributesPerVertexBuffer) === attributesPerVertexBuffer);
+
+ let shaderLocation = 0;
+ let attributeValue = 0;
+ const bufferLayouts = [];
+
+ let ExpectedDataConstructor;
+ switch (t.params.vertex_format) {
+ case 'uint32':
+ ExpectedDataConstructor = Uint32Array;
+ break;
+ case 'float32':
+ ExpectedDataConstructor = Float32Array;
+ break;
+ }
+
+ // Populate |bufferLayouts|, |vertexBufferData|, and |vertexBuffers|.
+ // We will use this to both create the render pipeline, and produce the
+ // expected data on the CPU.
+ // Attributes in each buffer will be interleaved.
+ const vertexBuffers = [];
+ const vertexBufferData = [];
+ for (let b = 0; b < t.params.vertex_buffer_count; ++b) {
+ const vertexBufferValues = [];
+
+ let offset = 0;
+ let stepMode = t.params.step_mode;
+
+ // If stepMode is mixed, alternate between vertex and instance.
+ if (stepMode === 'mixed') {
+ stepMode = ['vertex', 'instance'][b % 2];
+ }
+
+ let vertexOrInstanceCount;
+ switch (stepMode) {
+ case undefined:
+ case 'vertex':
+ vertexOrInstanceCount = vertexCount;
+ break;
+ case 'instance':
+ vertexOrInstanceCount = instanceCount;
+ break;
+ }
+
+ const attributes = [];
+ for (let a = 0; a < attributesPerVertexBuffer; ++a) {
+ const attribute = {
+ format: t.params.vertex_format,
+ shaderLocation,
+ offset,
+ };
+ attributes.push(attribute);
+
+ offset += ExpectedDataConstructor.BYTES_PER_ELEMENT;
+ shaderLocation += 1;
+ }
+
+ for (let v = 0; v < vertexOrInstanceCount; ++v) {
+ for (let a = 0; a < attributesPerVertexBuffer; ++a) {
+ vertexBufferValues.push(attributeValue);
+ attributeValue += 1.234; // Values will get rounded later if we make a Uint32Array.
+ }
+ }
+
+ bufferLayouts.push({
+ attributes,
+ arrayStride: offset,
+ stepMode,
+ });
+
+ const data = new ExpectedDataConstructor(vertexBufferValues);
+ vertexBufferData.push(data);
+ vertexBuffers.push(t.makeBufferWithContents(data, GPUBufferUsage.VERTEX));
+ }
+
+ // Create an array of shader locations [0, 1, 2, 3, ...] for easy iteration.
+ const vertexInputShaderLocations = new Array(shaderLocation).fill(0).map((_, i) => i);
+
+ // Create the expected data buffer.
+ const expectedData = new ExpectedDataConstructor(
+ vertexCount * instanceCount * vertexInputShaderLocations.length
+ );
+
+ // Populate the expected data. This is a CPU-side version of what we expect the shader
+ // to do.
+ for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) {
+ for (let instanceIndex = 0; instanceIndex < instanceCount; ++instanceIndex) {
+ bufferLayouts.forEach((bufferLayout, b) => {
+ for (const attribute of bufferLayout.attributes) {
+ const primitiveId = vertexCount * instanceIndex + vertexIndex;
+ const outputIndex =
+ primitiveId * vertexInputShaderLocations.length + attribute.shaderLocation;
+
+ let vertexOrInstanceIndex;
+ switch (bufferLayout.stepMode) {
+ case undefined:
+ case 'vertex':
+ vertexOrInstanceIndex = vertexIndex;
+ break;
+ case 'instance':
+ vertexOrInstanceIndex = instanceIndex;
+ break;
+ }
+
+ const view = new ExpectedDataConstructor(
+ vertexBufferData[b].buffer,
+ bufferLayout.arrayStride * vertexOrInstanceIndex + attribute.offset,
+ 1
+ );
+
+ expectedData[outputIndex] = view[0];
+ }
+ });
+ }
+ }
+
+ let wgslFormat;
+ switch (t.params.vertex_format) {
+ case 'uint32':
+ wgslFormat = 'u32';
+ break;
+ case 'float32':
+ wgslFormat = 'f32';
+ break;
+ }
+
+ // Maximum inter-stage shader location is 14, and we need to consume one for primitiveId, 12 for
+ // location 0 to 11, and combine the remaining vertex inputs into one location (one
+ // vec4<wgslFormat> when vertex_attribute_count === 16).
+ const interStageScalarShaderLocation = Math.min(shaderLocation, 12);
+ const interStageScalarShaderLocations = new Array(interStageScalarShaderLocation)
+ .fill(0)
+ .map((_, i) => i);
+
+ let accumulateVariableDeclarationsInVertexShader = '';
+ let accumulateVariableAssignmentsInVertexShader = '';
+ let accumulateVariableDeclarationsInFragmentShader = '';
+ let accumulateVariableAssignmentsInFragmentShader = '';
+ // The remaining 3 vertex attributes
+ if (t.params.vertex_attribute_count === 16) {
+ accumulateVariableDeclarationsInVertexShader = `
+ @location(13) @interpolate(flat) outAttrib13 : vec4<${wgslFormat}>,
+ `;
+ accumulateVariableAssignmentsInVertexShader = `
+ output.outAttrib13 =
+ vec4<${wgslFormat}>(input.attrib12, input.attrib13, input.attrib14, input.attrib15);
+ `;
+ accumulateVariableDeclarationsInFragmentShader = `
+ @location(13) @interpolate(flat) attrib13 : vec4<${wgslFormat}>,
+ `;
+ accumulateVariableAssignmentsInFragmentShader = `
+ outBuffer.primitives[input.primitiveId].attrib12 = input.attrib13.x;
+ outBuffer.primitives[input.primitiveId].attrib13 = input.attrib13.y;
+ outBuffer.primitives[input.primitiveId].attrib14 = input.attrib13.z;
+ outBuffer.primitives[input.primitiveId].attrib15 = input.attrib13.w;
+ `;
+ }
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+struct Inputs {
+ @builtin(vertex_index) vertexIndex : u32,
+ @builtin(instance_index) instanceIndex : u32,
+${vertexInputShaderLocations.map(i => ` @location(${i}) attrib${i} : ${wgslFormat},`).join('\n')}
+};
+
+struct Outputs {
+ @builtin(position) Position : vec4<f32>,
+${interStageScalarShaderLocations
+ .map(i => ` @location(${i}) @interpolate(flat) outAttrib${i} : ${wgslFormat},`)
+ .join('\n')}
+ @location(${interStageScalarShaderLocations.length}) @interpolate(flat) primitiveId : u32,
+${accumulateVariableDeclarationsInVertexShader}
+};
+
+@vertex fn main(input : Inputs) -> Outputs {
+ var output : Outputs;
+${interStageScalarShaderLocations.map(i => ` output.outAttrib${i} = input.attrib${i};`).join('\n')}
+${accumulateVariableAssignmentsInVertexShader}
+
+ output.primitiveId = input.instanceIndex * ${instanceCount}u + input.vertexIndex;
+ output.Position = vec4<f32>(0.0, 0.0, 0.5, 1.0);
+ return output;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ buffers: bufferLayouts,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+struct Inputs {
+${interStageScalarShaderLocations
+ .map(i => ` @location(${i}) @interpolate(flat) attrib${i} : ${wgslFormat},`)
+ .join('\n')}
+ @location(${interStageScalarShaderLocations.length}) @interpolate(flat) primitiveId : u32,
+${accumulateVariableDeclarationsInFragmentShader}
+};
+
+struct OutPrimitive {
+${vertexInputShaderLocations.map(i => ` attrib${i} : ${wgslFormat},`).join('\n')}
+};
+struct OutBuffer {
+ primitives : array<OutPrimitive>
+};
+@group(0) @binding(0) var<storage, read_write> outBuffer : OutBuffer;
+
+@fragment fn main(input : Inputs) {
+${interStageScalarShaderLocations
+ .map(i => ` outBuffer.primitives[input.primitiveId].attrib${i} = input.attrib${i};`)
+ .join('\n')}
+${accumulateVariableAssignmentsInFragmentShader}
+}
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [
+ {
+ format: 'rgba8unorm',
+ writeMask: 0,
+ },
+ ],
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ });
+
+ const resultBuffer = t.device.createBuffer({
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ size: vertexCount * instanceCount * vertexInputShaderLocations.length * 4,
+ });
+
+ const resultBindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: resultBuffer,
+ },
+ },
+ ],
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ // Dummy render attachment - not used (WebGPU doesn't allow using a render pass with no
+ // attachments)
+ view: t.device
+ .createTexture({
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [1],
+ format: 'rgba8unorm',
+ })
+ .createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ renderPass.setPipeline(pipeline);
+ renderPass.setBindGroup(0, resultBindGroup);
+ for (let i = 0; i < t.params.vertex_buffer_count; ++i) {
+ renderPass.setVertexBuffer(i, vertexBuffers[i]);
+ }
+ renderPass.draw(vertexCount, instanceCount);
+ renderPass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(resultBuffer, expectedData);
+ });
+
+g.test('vertex_attributes,formats')
+ .desc(
+ `Test all vertex formats are fetched correctly.
+
+ Runs a basic vertex shader which loads vertex data from two attributes which
+ may have different formats. Write data out to a storage buffer and check that
+ it was loaded correctly.
+
+ Params:
+ - vertex_format_1={...all_vertex_formats}
+ - vertex_format_2={...all_vertex_formats}
+ `
+ )
+ .unimplemented();
+
+g.test(`largeish_buffer`)
+ .desc(
+ `
+ Test a very large range of buffer is bound.
+ For a render pipeline that use a vertex step mode and a instance step mode vertex buffer, test
+ that :
+ - For draw, drawIndirect, drawIndexed and drawIndexedIndirect:
+ - The bound range of vertex step mode vertex buffer is significantly larger than necessary
+ - The bound range of instance step mode vertex buffer is significantly larger than necessary
+ - A large buffer is bound to an unused slot
+ - For drawIndexed and drawIndexedIndirect:
+ - The bound range of index buffer is significantly larger than necessary
+ - For drawIndirect and drawIndexedIndirect:
+ - The indirect buffer is significantly larger than necessary
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/indirect_draw.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/indirect_draw.spec.js
new file mode 100644
index 0000000000..429162d9c5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/indirect_draw.spec.js
@@ -0,0 +1,258 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for the indirect-specific aspects of drawIndirect/drawIndexedIndirect.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kDrawIndirectParametersSize,
+ kDrawIndexedIndirectParametersSize,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+const filled = new Uint8Array([0, 255, 0, 255]);
+const notFilled = new Uint8Array([0, 0, 0, 0]);
+
+const kRenderTargetFormat = 'rgba8unorm';
+
+class F extends GPUTest {
+ MakeIndexBuffer() {
+ return this.makeBufferWithContents(
+ new Uint32Array([
+ 0,
+ 1,
+ 2, // The bottom left triangle
+ 1,
+ 2,
+ 3, // The top right triangle
+ ]),
+ GPUBufferUsage.INDEX
+ );
+ }
+
+ MakeVertexBuffer(isIndexed) {
+ const vertices = isIndexed
+ ? [-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]
+ : [
+ // The bottom left triangle
+ -1.0,
+ 1.0,
+ 1.0,
+ -1.0,
+ -1.0,
+ -1.0,
+
+ // The top right triangle
+ -1.0,
+ 1.0,
+ 1.0,
+ -1.0,
+ 1.0,
+ 1.0,
+ ];
+
+ return this.makeBufferWithContents(new Float32Array(vertices), GPUBufferUsage.VERTEX);
+ }
+
+ MakeIndirectBuffer(isIndexed, indirectOffset) {
+ const o = indirectOffset / Uint32Array.BYTES_PER_ELEMENT;
+
+ const parametersSize = isIndexed
+ ? kDrawIndexedIndirectParametersSize
+ : kDrawIndirectParametersSize;
+ const arraySize = o + parametersSize * 2;
+
+ const indirectBuffer = [...Array(arraySize)].map(() => Math.floor(Math.random() * 100));
+
+ if (isIndexed) {
+ // draw args that will draw the left bottom triangle (expected call)
+ indirectBuffer[o] = 3; // indexCount
+ indirectBuffer[o + 1] = 1; // instanceCount
+ indirectBuffer[o + 2] = 0; // firstIndex
+ indirectBuffer[o + 3] = 0; // baseVertex
+ indirectBuffer[o + 4] = 0; // firstInstance
+
+ // draw args that will draw both triangles
+ indirectBuffer[o + 5] = 6; // indexCount
+ indirectBuffer[o + 6] = 1; // instanceCount
+ indirectBuffer[o + 7] = 0; // firstIndex
+ indirectBuffer[o + 8] = 0; // baseVertex
+ indirectBuffer[o + 9] = 0; // firstInstance
+
+ if (o >= parametersSize) {
+ // draw args that will draw the right top triangle
+ indirectBuffer[o - 5] = 3; // indexCount
+ indirectBuffer[o - 4] = 1; // instanceCount
+ indirectBuffer[o - 3] = 3; // firstIndex
+ indirectBuffer[o - 2] = 0; // baseVertex
+ indirectBuffer[o - 1] = 0; // firstInstance
+ }
+
+ if (o >= parametersSize * 2) {
+ // draw args that will draw nothing
+ indirectBuffer[0] = 0; // indexCount
+ indirectBuffer[1] = 0; // instanceCount
+ indirectBuffer[2] = 0; // firstIndex
+ indirectBuffer[3] = 0; // baseVertex
+ indirectBuffer[4] = 0; // firstInstance
+ }
+ } else {
+ // draw args that will draw the left bottom triangle (expected call)
+ indirectBuffer[o] = 3; // vertexCount
+ indirectBuffer[o + 1] = 1; // instanceCount
+ indirectBuffer[o + 2] = 0; // firstVertex
+ indirectBuffer[o + 3] = 0; // firstInstance
+
+ // draw args that will draw both triangles
+ indirectBuffer[o + 4] = 6; // vertexCount
+ indirectBuffer[o + 5] = 1; // instanceCount
+ indirectBuffer[o + 6] = 0; // firstVertex
+ indirectBuffer[o + 7] = 0; // firstInstance
+
+ if (o >= parametersSize) {
+ // draw args that will draw the right top triangle
+ indirectBuffer[o - 4] = 3; // vertexCount
+ indirectBuffer[o - 3] = 1; // instanceCount
+ indirectBuffer[o - 2] = 3; // firstVertex
+ indirectBuffer[o - 1] = 0; // firstInstance
+ }
+
+ if (o >= parametersSize * 2) {
+ // draw args that will draw nothing
+ indirectBuffer[0] = 0; // vertexCount
+ indirectBuffer[1] = 0; // instanceCount
+ indirectBuffer[2] = 0; // firstVertex
+ indirectBuffer[3] = 0; // firstInstance
+ }
+ }
+
+ return this.makeBufferWithContents(new Uint32Array(indirectBuffer), GPUBufferUsage.INDIRECT);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('basics')
+ .desc(
+ `Test that the indirect draw parameters are tightly packed for drawIndirect and drawIndexedIndirect.
+An indirectBuffer is created based on indirectOffset. The actual draw args being used indicated by the
+indirectOffset is going to draw a left bottom triangle.
+While the remaining indirectBuffer is populated with random numbers or draw args
+that draw right top triangle, both, or nothing which will fail the color check.
+The test will check render target to see if only the left bottom area is filled,
+meaning the expected draw args is uploaded correctly by the indirectBuffer and indirectOffset.
+
+Params:
+ - draw{Indirect, IndexedIndirect}
+ - indirectOffset= {0, 4, k * sizeof(args struct), k * sizeof(args struct) + 4}
+ `
+ )
+ .params(u =>
+ u
+ .combine('isIndexed', [true, false])
+ .beginSubcases()
+ .expand('indirectOffset', p => {
+ const indirectDrawParametersSize = p.isIndexed
+ ? kDrawIndexedIndirectParametersSize * Uint32Array.BYTES_PER_ELEMENT
+ : kDrawIndirectParametersSize * Uint32Array.BYTES_PER_ELEMENT;
+ return [
+ 0,
+ Uint32Array.BYTES_PER_ELEMENT,
+ 1 * indirectDrawParametersSize,
+ 1 * indirectDrawParametersSize + Uint32Array.BYTES_PER_ELEMENT,
+ 3 * indirectDrawParametersSize,
+ 3 * indirectDrawParametersSize + Uint32Array.BYTES_PER_ELEMENT,
+ 99 * indirectDrawParametersSize,
+ 99 * indirectDrawParametersSize + Uint32Array.BYTES_PER_ELEMENT,
+ ];
+ })
+ )
+ .fn(t => {
+ const { isIndexed, indirectOffset } = t.params;
+
+ const vertexBuffer = t.MakeVertexBuffer(isIndexed);
+ const indirectBuffer = t.MakeIndirectBuffer(isIndexed, indirectOffset);
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `@vertex fn main(@location(0) pos : vec2<f32>) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(pos, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ attributes: [
+ {
+ shaderLocation: 0,
+ format: 'float32x2',
+ offset: 0,
+ },
+ ],
+
+ arrayStride: 2 * Float32Array.BYTES_PER_ELEMENT,
+ },
+ ],
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [
+ {
+ format: kRenderTargetFormat,
+ },
+ ],
+ },
+ });
+
+ const renderTarget = t.device.createTexture({
+ size: [4, 4],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ format: kRenderTargetFormat,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(pipeline);
+ renderPass.setVertexBuffer(0, vertexBuffer, 0);
+
+ if (isIndexed) {
+ renderPass.setIndexBuffer(t.MakeIndexBuffer(), 'uint32', 0);
+ renderPass.drawIndexedIndirect(indirectBuffer, indirectOffset);
+ } else {
+ renderPass.drawIndirect(indirectBuffer, indirectOffset);
+ }
+ renderPass.end();
+ t.queue.submit([commandEncoder.finish()]);
+
+ // The bottom left area is filled
+ t.expectSinglePixelIn2DTexture(
+ renderTarget,
+ kRenderTargetFormat,
+ { x: 0, y: 1 },
+ { exp: filled }
+ );
+
+ // The top right area is not filled
+ t.expectSinglePixelIn2DTexture(
+ renderTarget,
+ kRenderTargetFormat,
+ { x: 1, y: 0 },
+ { exp: notFilled }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/robust_access_index.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/robust_access_index.spec.js
new file mode 100644
index 0000000000..6b052b895d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/robust_access_index.spec.js
@@ -0,0 +1,9 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO: Test that drawIndexedIndirect accesses the index buffer robustly.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/stencil.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/stencil.spec.js
new file mode 100644
index 0000000000..27620111cc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/rendering/stencil.spec.js
@@ -0,0 +1,575 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test related to stencil states, stencil op, compare func, etc.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+
+import { kDepthStencilFormats, kTextureFormatInfo } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+
+const kStencilFormats = kDepthStencilFormats.filter(format => kTextureFormatInfo[format].stencil);
+
+const kBaseColor = new Float32Array([1.0, 1.0, 1.0, 1.0]);
+const kRedStencilColor = new Float32Array([1.0, 0.0, 0.0, 1.0]);
+const kGreenStencilColor = new Float32Array([0.0, 1.0, 0.0, 1.0]);
+
+class StencilTest extends GPUTest {
+ checkStencilOperation(
+ depthStencilFormat,
+ testStencilState,
+ initialStencil,
+ _expectedStencil,
+ depthCompare = 'always'
+ ) {
+ const kReferenceStencil = 3;
+
+ const baseStencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ passOp: 'replace',
+ };
+
+ const stencilState = {
+ compare: 'equal',
+ failOp: 'keep',
+ passOp: 'keep',
+ };
+
+ const baseState = {
+ format: depthStencilFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: baseStencilState,
+ stencilBack: baseStencilState,
+ };
+
+ const testState = {
+ format: depthStencilFormat,
+ depthWriteEnabled: false,
+ depthCompare,
+ stencilFront: testStencilState,
+ stencilBack: testStencilState,
+ };
+
+ const testState2 = {
+ format: depthStencilFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ };
+
+ const testStates = [
+ // Draw the base triangle with stencil reference 1. This clears the stencil buffer to 1.
+ { state: baseState, color: kBaseColor, stencil: initialStencil },
+ { state: testState, color: kRedStencilColor, stencil: kReferenceStencil },
+ { state: testState2, color: kGreenStencilColor, stencil: _expectedStencil },
+ ];
+
+ this.runStencilStateTest(depthStencilFormat, testStates, kGreenStencilColor);
+ }
+
+ checkStencilCompareFunction(depthStencilFormat, compareFunction, stencilRefValue, expectedColor) {
+ const baseStencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ passOp: 'replace',
+ };
+
+ const stencilState = {
+ compare: compareFunction,
+ failOp: 'keep',
+ passOp: 'keep',
+ };
+
+ const baseState = {
+ format: depthStencilFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: baseStencilState,
+ stencilBack: baseStencilState,
+ };
+
+ const testState = {
+ format: depthStencilFormat,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ };
+
+ const testStates = [
+ // Draw the base triangle with stencil reference 1. This clears the stencil buffer to 1.
+ { state: baseState, color: kBaseColor, stencil: 1 },
+ { state: testState, color: kGreenStencilColor, stencil: stencilRefValue },
+ ];
+
+ this.runStencilStateTest(depthStencilFormat, testStates, expectedColor);
+ }
+
+ runStencilStateTest(
+ depthStencilFormat,
+ testStates,
+ expectedColor,
+ isSingleEncoderMultiplePass = false
+ ) {
+ const renderTargetFormat = 'rgba8unorm';
+ const renderTarget = this.device.createTexture({
+ format: renderTargetFormat,
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const depthTexture = this.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: depthStencilFormat,
+ sampleCount: 1,
+ mipLevelCount: 1,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST,
+ });
+
+ const depthStencilAttachment = {
+ view: depthTexture.createView(),
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilLoadOp: 'load',
+ stencilStoreOp: 'store',
+ };
+
+ const encoder = this.device.createCommandEncoder();
+ let pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ loadOp: 'load',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+
+ if (isSingleEncoderMultiplePass) {
+ pass.end();
+ }
+
+ // Draw a triangle with the given stencil reference and the comparison function.
+ // The color will be kGreenStencilColor if the stencil test passes, and kBaseColor if not.
+ for (const test of testStates) {
+ if (isSingleEncoderMultiplePass) {
+ pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ storeOp: 'store',
+ loadOp: 'load',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+ }
+ const testPipeline = this.createRenderPipelineForTest(test.state);
+ pass.setPipeline(testPipeline);
+ if (test.stencil !== undefined) {
+ pass.setStencilReference(test.stencil);
+ }
+ pass.setBindGroup(
+ 0,
+ this.createBindGroupForTest(testPipeline.getBindGroupLayout(0), test.color)
+ );
+
+ pass.draw(1);
+
+ if (isSingleEncoderMultiplePass) {
+ pass.end();
+ }
+ }
+
+ if (!isSingleEncoderMultiplePass) {
+ pass.end();
+ }
+ this.device.queue.submit([encoder.finish()]);
+
+ const expColor = {
+ R: expectedColor[0],
+ G: expectedColor[1],
+ B: expectedColor[2],
+ A: expectedColor[3],
+ };
+ const expTexelView = TexelView.fromTexelsAsColors(renderTargetFormat, coords => expColor);
+
+ const result = textureContentIsOKByT2B(
+ this,
+ { texture: renderTarget },
+ [1, 1],
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ this.eventualExpectOK(result);
+ this.trackForCleanup(renderTarget);
+ }
+
+ createRenderPipelineForTest(depthStencil) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ targets: [{ format: 'rgba8unorm' }],
+ module: this.device.createShaderModule({
+ code: `
+ struct Params {
+ color : vec4<f32>
+ }
+ @group(0) @binding(0) var<uniform> params : Params;
+
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(params.color);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ primitive: { topology: 'point-list' },
+ depthStencil,
+ });
+ }
+
+ createBindGroupForTest(layout, data) {
+ return this.device.createBindGroup({
+ layout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: this.makeBufferWithContents(data, GPUBufferUsage.UNIFORM),
+ },
+ },
+ ],
+ });
+ }
+}
+
+export const g = makeTestGroup(StencilTest);
+
+g.test('stencil_compare_func')
+ .desc(
+ `
+ Tests that stencil comparison functions with the stencil reference value works as expected.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kStencilFormats)
+ .combineWithParams([
+ { stencilCompare: 'always', stencilRefValue: 0, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'always', stencilRefValue: 1, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'always', stencilRefValue: 2, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'equal', stencilRefValue: 0, _expectedColor: kBaseColor },
+ { stencilCompare: 'equal', stencilRefValue: 1, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'equal', stencilRefValue: 2, _expectedColor: kBaseColor },
+ { stencilCompare: 'greater', stencilRefValue: 0, _expectedColor: kBaseColor },
+ { stencilCompare: 'greater', stencilRefValue: 1, _expectedColor: kBaseColor },
+ { stencilCompare: 'greater', stencilRefValue: 2, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'greater-equal', stencilRefValue: 0, _expectedColor: kBaseColor },
+ { stencilCompare: 'greater-equal', stencilRefValue: 1, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'greater-equal', stencilRefValue: 2, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'less', stencilRefValue: 0, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'less', stencilRefValue: 1, _expectedColor: kBaseColor },
+ { stencilCompare: 'less', stencilRefValue: 2, _expectedColor: kBaseColor },
+ { stencilCompare: 'less-equal', stencilRefValue: 0, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'less-equal', stencilRefValue: 1, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'less-equal', stencilRefValue: 2, _expectedColor: kBaseColor },
+ { stencilCompare: 'never', stencilRefValue: 0, _expectedColor: kBaseColor },
+ { stencilCompare: 'never', stencilRefValue: 1, _expectedColor: kBaseColor },
+ { stencilCompare: 'never', stencilRefValue: 2, _expectedColor: kBaseColor },
+ { stencilCompare: 'not-equal', stencilRefValue: 0, _expectedColor: kGreenStencilColor },
+ { stencilCompare: 'not-equal', stencilRefValue: 1, _expectedColor: kBaseColor },
+ { stencilCompare: 'not-equal', stencilRefValue: 2, _expectedColor: kGreenStencilColor },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format, stencilCompare, stencilRefValue, _expectedColor } = t.params;
+
+ t.checkStencilCompareFunction(format, stencilCompare, stencilRefValue, _expectedColor);
+ });
+
+g.test('stencil_passOp_operation')
+ .desc(
+ `
+ Test that the stencil operation is executed on stencil pass. A triangle is drawn with the 'always'
+ comparison function, so it should pass. Then, test that each pass stencil operation works with the
+ given stencil values correctly as expected. For example,
+ - If the pass operation is 'keep', it keeps the initial stencil value.
+ - If the pass operation is 'replace', it replaces the initial stencil value with the reference
+ stencil value.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kStencilFormats)
+ .combineWithParams([
+ { passOp: 'keep', initialStencil: 1, _expectedStencil: 1 },
+ { passOp: 'zero', initialStencil: 1, _expectedStencil: 0 },
+ { passOp: 'replace', initialStencil: 1, _expectedStencil: 3 },
+ { passOp: 'invert', initialStencil: 0xf0, _expectedStencil: 0x0f },
+ { passOp: 'increment-clamp', initialStencil: 1, _expectedStencil: 2 },
+ { passOp: 'increment-clamp', initialStencil: 0xff, _expectedStencil: 0xff },
+ { passOp: 'increment-wrap', initialStencil: 1, _expectedStencil: 2 },
+ { passOp: 'increment-wrap', initialStencil: 0xff, _expectedStencil: 0 },
+ { passOp: 'decrement-clamp', initialStencil: 1, _expectedStencil: 0 },
+ { passOp: 'decrement-clamp', initialStencil: 0, _expectedStencil: 0 },
+ { passOp: 'decrement-wrap', initialStencil: 1, _expectedStencil: 0 },
+ { passOp: 'decrement-wrap', initialStencil: 0, _expectedStencil: 0xff },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format, passOp, initialStencil, _expectedStencil } = t.params;
+
+ const stencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ passOp,
+ };
+
+ t.checkStencilOperation(format, stencilState, initialStencil, _expectedStencil);
+ });
+
+g.test('stencil_failOp_operation')
+ .desc(
+ `
+ Test that the stencil operation is executed on stencil fail. A triangle is drawn with the 'never'
+ comparison function, so it should fail. Then, test that each fail stencil operation works with the
+ given stencil values correctly as expected. For example,
+ - If the fail operation is 'keep', it keeps the initial stencil value.
+ - If the fail operation is 'replace', it replaces the initial stencil value with the reference
+ stencil value.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kStencilFormats)
+ .combineWithParams([
+ { failOp: 'keep', initialStencil: 1, _expectedStencil: 1 },
+ { failOp: 'zero', initialStencil: 1, _expectedStencil: 0 },
+ { failOp: 'replace', initialStencil: 1, _expectedStencil: 3 },
+ { failOp: 'invert', initialStencil: 0xf0, _expectedStencil: 0x0f },
+ { failOp: 'increment-clamp', initialStencil: 1, _expectedStencil: 2 },
+ { failOp: 'increment-clamp', initialStencil: 0xff, _expectedStencil: 0xff },
+ { failOp: 'increment-wrap', initialStencil: 1, _expectedStencil: 2 },
+ { failOp: 'increment-wrap', initialStencil: 0xff, _expectedStencil: 0 },
+ { failOp: 'decrement-clamp', initialStencil: 1, _expectedStencil: 0 },
+ { failOp: 'decrement-clamp', initialStencil: 0, _expectedStencil: 0 },
+ { failOp: 'decrement-wrap', initialStencil: 2, _expectedStencil: 1 },
+ { failOp: 'decrement-wrap', initialStencil: 1, _expectedStencil: 0 },
+ { failOp: 'decrement-wrap', initialStencil: 0, _expectedStencil: 0xff },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format, failOp, initialStencil, _expectedStencil } = t.params;
+
+ const stencilState = {
+ compare: 'never',
+ failOp,
+ passOp: 'keep',
+ };
+
+ // Draw the base triangle with stencil reference 1. This clears the stencil buffer to 1.
+ // Always fails because the comparison never passes. Therefore red is never drawn, and the
+ // stencil contents may be updated according to `operation`.
+ t.checkStencilOperation(format, stencilState, initialStencil, _expectedStencil);
+ });
+
+g.test('stencil_depthFailOp_operation')
+ .desc(
+ `
+ Test that the stencil operation is executed on depthCompare fail. A triangle is drawn with the
+ 'never' depthCompare, so it should fail the depth test. Then, test that each 'depthFailOp' stencil operation
+ works with the given stencil values correctly as expected. For example,
+ - If the depthFailOp operation is 'keep', it keeps the initial stencil value.
+ - If the depthFailOp operation is 'replace', it replaces the initial stencil value with the
+ reference stencil value.
+ `
+ )
+ .params(u =>
+ u //
+ .combine(
+ 'format',
+ kDepthStencilFormats.filter(format => {
+ const info = kTextureFormatInfo[format];
+ return info.depth && info.stencil;
+ })
+ )
+ .combineWithParams([
+ { depthFailOp: 'keep', initialStencil: 1, _expectedStencil: 1 },
+ { depthFailOp: 'zero', initialStencil: 1, _expectedStencil: 0 },
+ { depthFailOp: 'replace', initialStencil: 1, _expectedStencil: 3 },
+ { depthFailOp: 'invert', initialStencil: 0xf0, _expectedStencil: 0x0f },
+ { depthFailOp: 'increment-clamp', initialStencil: 1, _expectedStencil: 2 },
+ { depthFailOp: 'increment-clamp', initialStencil: 0xff, _expectedStencil: 0xff },
+ { depthFailOp: 'increment-wrap', initialStencil: 1, _expectedStencil: 2 },
+ { depthFailOp: 'increment-wrap', initialStencil: 0xff, _expectedStencil: 0 },
+ { depthFailOp: 'decrement-clamp', initialStencil: 1, _expectedStencil: 0 },
+ { depthFailOp: 'decrement-clamp', initialStencil: 0, _expectedStencil: 0 },
+ { depthFailOp: 'decrement-wrap', initialStencil: 2, _expectedStencil: 1 },
+ { depthFailOp: 'decrement-wrap', initialStencil: 1, _expectedStencil: 0 },
+ { depthFailOp: 'decrement-wrap', initialStencil: 0, _expectedStencil: 0xff },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format, depthFailOp, initialStencil, _expectedStencil } = t.params;
+
+ const stencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ passOp: 'keep',
+ depthFailOp,
+ };
+
+ // Call checkStencilOperation function with enabling the depthTest to test that the depthFailOp
+ // stencil operation works as expected.
+ t.checkStencilOperation(format, stencilState, initialStencil, _expectedStencil, 'never');
+ });
+
+g.test('stencil_read_write_mask')
+ .desc(
+ `
+ Tests that setting a stencil read/write masks work. Basically, The base triangle sets 3 to the
+ stencil, and then try to draw a triangle with different stencil values.
+ - In case that 'write' mask is 1,
+ * If the stencil of the triangle is 1, it draws because
+ 'base stencil(3) & write mask(1) == triangle stencil(1)'.
+ * If the stencil of the triangle is 2, it does not draw because
+ 'base stencil(3) & write mask(1) != triangle stencil(2)'.
+
+ - In case that 'read' mask is 2,
+ * If the stencil of the triangle is 1, it does not draw because
+ 'base stencil(3) & read mask(2) != triangle stencil(1)'.
+ * If the stencil of the triangle is 2, it draws because
+ 'base stencil(3) & read mask(2) == triangle stencil(2)'.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kStencilFormats)
+ .combineWithParams([
+ { maskType: 'write', stencilRefValue: 1, _expectedColor: kRedStencilColor },
+ { maskType: 'write', stencilRefValue: 2, _expectedColor: kBaseColor },
+ { maskType: 'read', stencilRefValue: 1, _expectedColor: kBaseColor },
+ { maskType: 'read', stencilRefValue: 2, _expectedColor: kRedStencilColor },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format, maskType, stencilRefValue, _expectedColor } = t.params;
+
+ const baseStencilState = {
+ compare: 'always',
+ failOp: 'keep',
+ passOp: 'replace',
+ };
+
+ const stencilState = {
+ compare: 'equal',
+ failOp: 'keep',
+ passOp: 'keep',
+ };
+
+ const baseState = {
+ format,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: baseStencilState,
+ stencilBack: baseStencilState,
+ stencilReadMask: 0xff,
+ stencilWriteMask: maskType === 'write' ? 0x1 : 0xff,
+ };
+
+ const testState = {
+ format,
+ depthWriteEnabled: false,
+ depthCompare: 'always',
+ stencilFront: stencilState,
+ stencilBack: stencilState,
+ stencilReadMask: maskType === 'read' ? 0x2 : 0xff,
+ stencilWriteMask: 0xff,
+ };
+
+ const testStates = [
+ // Draw the base triangle with stencil reference 3. This clears the stencil buffer to 3.
+ { state: baseState, color: kBaseColor, stencil: 3 },
+ { state: testState, color: kRedStencilColor, stencil: stencilRefValue },
+ ];
+
+ t.runStencilStateTest(format, testStates, _expectedColor);
+ });
+
+g.test('stencil_reference_initialized')
+ .desc('Test that stencil reference is initialized as zero for new render pass.')
+ .params(u => u.combine('format', kStencilFormats))
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format } = t.params;
+
+ const baseStencilState = {
+ compare: 'always',
+ passOp: 'replace',
+ };
+
+ const testStencilState = {
+ compare: 'equal',
+ passOp: 'keep',
+ };
+
+ const baseState = {
+ format,
+ stencilFront: baseStencilState,
+ stencilBack: baseStencilState,
+ };
+
+ const testState = {
+ format,
+ stencilFront: testStencilState,
+ stencilBack: testStencilState,
+ };
+
+ // First pass sets the stencil to 0x1, the second pass sets the stencil to its default
+ // value, and the third pass tests if the stencil is zero.
+ const testStates = [
+ { state: baseState, color: kBaseColor, stencil: 0x1 },
+ { state: baseState, color: kRedStencilColor, stencil: undefined },
+ { state: testState, color: kGreenStencilColor, stencil: 0x0 },
+ ];
+
+ // The third draw should pass the stencil test since the second pass set it to default zero.
+ t.runStencilStateTest(format, testStates, kGreenStencilColor, true);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/buffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/buffer.spec.js
new file mode 100644
index 0000000000..4e0ff8b77d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/buffer.spec.js
@@ -0,0 +1,886 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../common/util/util.js';
+import { GPUConst } from '../../../constants.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { getTextureCopyLayout } from '../../../util/texture/layout.js';
+
+export const description = `
+Test uninitialized buffers are initialized to zero when read
+(or read-written, e.g. with depth write or atomics).
+
+Note that:
+- We don't need 'copy_buffer_to_buffer_copy_destination' here because there has already been an
+ operation test 'command_buffer.copyBufferToBuffer.single' that provides the same functionality.
+`;
+
+const kMapModeOptions = [GPUConst.MapMode.READ, GPUConst.MapMode.WRITE];
+const kBufferUsagesForMappedAtCreationTests = [
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ,
+ GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.MAP_WRITE,
+ GPUConst.BufferUsage.COPY_SRC,
+];
+
+class F extends GPUTest {
+ GetBufferUsageFromMapMode(mapMode) {
+ switch (mapMode) {
+ case GPUMapMode.READ:
+ return GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ;
+ case GPUMapMode.WRITE:
+ return GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE;
+ default:
+ unreachable();
+ return 0;
+ }
+ }
+
+ async CheckGPUBufferContent(buffer, bufferUsage, expectedData) {
+ const mappable = bufferUsage & GPUBufferUsage.MAP_READ;
+ this.expectGPUBufferValuesEqual(buffer, expectedData, 0, { method: mappable ? 'map' : 'copy' });
+ }
+
+ TestBufferZeroInitInBindGroup(computeShaderModule, buffer, bufferOffset, boundBufferSize) {
+ const computePipeline = this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: computeShaderModule,
+ entryPoint: 'main',
+ },
+ });
+ const outputTexture = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING,
+ });
+ this.trackForCleanup(outputTexture);
+ const bindGroup = this.device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer,
+ offset: bufferOffset,
+ size: boundBufferSize,
+ },
+ },
+ {
+ binding: 1,
+ resource: outputTexture.createView(),
+ },
+ ],
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const computePass = encoder.beginComputePass();
+ computePass.setBindGroup(0, bindGroup);
+ computePass.setPipeline(computePipeline);
+ computePass.dispatchWorkgroups(1);
+ computePass.end();
+ this.queue.submit([encoder.finish()]);
+
+ this.CheckBufferAndOutputTexture(buffer, boundBufferSize + bufferOffset, outputTexture);
+ }
+
+ CreateRenderPipelineForTest(vertexShaderModule, testVertexBuffer) {
+ const renderPipelineDescriptor = {
+ layout: 'auto',
+ vertex: {
+ module: vertexShaderModule,
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment
+ fn main(@location(0) i_color : vec4<f32>) -> @location(0) vec4<f32> {
+ return i_color;
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ };
+ if (testVertexBuffer) {
+ renderPipelineDescriptor.vertex.buffers = [
+ {
+ arrayStride: 16,
+ attributes: [{ format: 'float32x4', offset: 0, shaderLocation: 0 }],
+ },
+ ];
+ }
+
+ return this.device.createRenderPipeline(renderPipelineDescriptor);
+ }
+
+ RecordInitializeTextureColor(encoder, texture, color) {
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: texture.createView(),
+ clearValue: color,
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.end();
+ }
+
+ CheckBufferAndOutputTexture(
+ buffer,
+ bufferSize,
+ outputTexture,
+ outputTextureSize = [1, 1, 1],
+ outputTextureColor = { R: 0.0, G: 1.0, B: 0.0, A: 1.0 }
+ ) {
+ this.expectSingleColor(outputTexture, 'rgba8unorm', {
+ size: outputTextureSize,
+ exp: outputTextureColor,
+ });
+
+ const expectedBufferData = new Uint8Array(bufferSize);
+ this.expectGPUBufferValuesEqual(buffer, expectedBufferData);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('partial_write_buffer')
+ .desc(
+ `Verify when we upload data to a part of a buffer with writeBuffer() just after the creation of
+the buffer, the remaining part of that buffer will be initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('offset', [0, 8, -12]))
+ .fn(async t => {
+ const { offset } = t.params;
+ const bufferSize = 32;
+ const appliedOffset = offset >= 0 ? offset : bufferSize + offset;
+
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ const copySize = 12;
+ const writeData = new Uint8Array(copySize);
+ const expectedData = new Uint8Array(bufferSize);
+ for (let i = 0; i < copySize; ++i) {
+ expectedData[appliedOffset + i] = writeData[i] = i + 1;
+ }
+ t.queue.writeBuffer(buffer, appliedOffset, writeData, 0);
+
+ t.expectGPUBufferValuesEqual(buffer, expectedData);
+ });
+
+g.test('map_whole_buffer')
+ .desc(
+ `Verify when we map the whole range of a mappable GPUBuffer to a typed array buffer just after
+creating the GPUBuffer, the contents of both the typed array buffer and the GPUBuffer itself
+have already been initialized to 0.`
+ )
+ .params(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+
+ const bufferSize = 32;
+ const bufferUsage = t.GetBufferUsageFromMapMode(mapMode);
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ await buffer.mapAsync(mapMode);
+ const readData = new Uint8Array(buffer.getMappedRange());
+ for (let i = 0; i < bufferSize; ++i) {
+ t.expect(readData[i] === 0);
+ }
+ buffer.unmap();
+
+ const expectedData = new Uint8Array(bufferSize);
+ await t.CheckGPUBufferContent(buffer, bufferUsage, expectedData);
+ });
+
+g.test('map_partial_buffer')
+ .desc(
+ `Verify when we map a subrange of a mappable GPUBuffer to a typed array buffer just after the
+creation of the GPUBuffer, the contents of both the typed array buffer and the GPUBuffer have
+already been initialized to 0.`
+ )
+ .params(u => u.combine('mapMode', kMapModeOptions).beginSubcases().combine('offset', [0, 8, -16]))
+ .fn(async t => {
+ const { mapMode, offset } = t.params;
+ const bufferSize = 32;
+ const appliedOffset = offset >= 0 ? offset : bufferSize + offset;
+
+ const bufferUsage = t.GetBufferUsageFromMapMode(mapMode);
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ const expectedData = new Uint8Array(bufferSize);
+ {
+ const mapSize = 16;
+ await buffer.mapAsync(mapMode, appliedOffset, mapSize);
+ const mappedData = new Uint8Array(buffer.getMappedRange(appliedOffset, mapSize));
+ for (let i = 0; i < mapSize; ++i) {
+ t.expect(mappedData[i] === 0);
+ if (mapMode === GPUMapMode.WRITE) {
+ mappedData[i] = expectedData[appliedOffset + i] = i + 1;
+ }
+ }
+ buffer.unmap();
+ }
+
+ await t.CheckGPUBufferContent(buffer, bufferUsage, expectedData);
+ });
+
+g.test('mapped_at_creation_whole_buffer')
+ .desc(
+ `Verify when we call getMappedRange() at the whole range of a GPUBuffer created with
+mappedAtCreation === true just after its creation, the contents of both the returned typed
+array buffer of getMappedRange() and the GPUBuffer itself have all been initialized to 0.`
+ )
+ .params(u => u.combine('bufferUsage', kBufferUsagesForMappedAtCreationTests))
+ .fn(async t => {
+ const { bufferUsage } = t.params;
+
+ const bufferSize = 32;
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ const mapped = new Uint8Array(buffer.getMappedRange());
+ for (let i = 0; i < bufferSize; ++i) {
+ t.expect(mapped[i] === 0);
+ }
+ buffer.unmap();
+
+ const expectedData = new Uint8Array(bufferSize);
+ await t.CheckGPUBufferContent(buffer, bufferUsage, expectedData);
+ });
+
+g.test('mapped_at_creation_partial_buffer')
+ .desc(
+ `Verify when we call getMappedRange() at a subrange of a GPUBuffer created with
+mappedAtCreation === true just after its creation, the contents of both the returned typed
+array buffer of getMappedRange() and the GPUBuffer itself have all been initialized to 0.`
+ )
+ .params(u =>
+ u
+ .combine('bufferUsage', kBufferUsagesForMappedAtCreationTests)
+ .beginSubcases()
+ .combine('offset', [0, 8, -16])
+ )
+ .fn(async t => {
+ const { bufferUsage, offset } = t.params;
+ const bufferSize = 32;
+ const appliedOffset = offset >= 0 ? offset : bufferSize + offset;
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ const expectedData = new Uint8Array(bufferSize);
+ {
+ const mappedSize = 12;
+ const mapped = new Uint8Array(buffer.getMappedRange(appliedOffset, mappedSize));
+ for (let i = 0; i < mappedSize; ++i) {
+ t.expect(mapped[i] === 0);
+ if (!(bufferUsage & GPUBufferUsage.MAP_READ)) {
+ mapped[i] = expectedData[appliedOffset + i] = i + 1;
+ }
+ }
+ buffer.unmap();
+ }
+
+ await t.CheckGPUBufferContent(buffer, bufferUsage, expectedData);
+ });
+
+g.test('copy_buffer_to_buffer_copy_source')
+ .desc(
+ `Verify when the first usage of a GPUBuffer is being used as the source buffer of
+CopyBufferToBuffer(), the contents of the GPUBuffer have already been initialized to 0.`
+ )
+ .fn(async t => {
+ const bufferSize = 32;
+ const bufferUsage = GPUBufferUsage.COPY_SRC;
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ const expectedData = new Uint8Array(bufferSize);
+ // copyBufferToBuffer() is called inside t.CheckGPUBufferContent().
+ await t.CheckGPUBufferContent(buffer, bufferUsage, expectedData);
+ });
+
+g.test('copy_buffer_to_texture')
+ .desc(
+ `Verify when the first usage of a GPUBuffer is being used as the source buffer of
+CopyBufferToTexture(), the contents of the GPUBuffer have already been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 8]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+ const textureSize = [8, 8, 1];
+ const dstTextureFormat = 'rgba8unorm';
+
+ const dstTexture = t.device.createTexture({
+ size: textureSize,
+ format: dstTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+ t.trackForCleanup(dstTexture);
+ const layout = getTextureCopyLayout(dstTextureFormat, '2d', textureSize);
+ const srcBufferSize = layout.byteLength + bufferOffset;
+ const srcBufferUsage = GPUBufferUsage.COPY_SRC;
+ const srcBuffer = t.device.createBuffer({
+ size: srcBufferSize,
+ usage: srcBufferUsage,
+ });
+ t.trackForCleanup(srcBuffer);
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToTexture(
+ {
+ buffer: srcBuffer,
+ offset: bufferOffset,
+ bytesPerRow: layout.bytesPerRow,
+ rowsPerImage: layout.rowsPerImage,
+ },
+ { texture: dstTexture },
+ textureSize
+ );
+
+ t.queue.submit([encoder.finish()]);
+
+ t.CheckBufferAndOutputTexture(srcBuffer, srcBufferSize, dstTexture, textureSize, {
+ R: 0.0,
+ G: 0.0,
+ B: 0.0,
+ A: 0.0,
+ });
+ });
+
+g.test('resolve_query_set_to_partial_buffer')
+ .desc(
+ `Verify when we resolve a query set into a GPUBuffer just after creating that GPUBuffer, the
+remaining part of it will be initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 256]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+ const bufferSize = bufferOffset + 8;
+ const bufferUsage = GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE;
+ const dstBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(dstBuffer);
+
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: 1 });
+ const encoder = t.device.createCommandEncoder();
+ encoder.resolveQuerySet(querySet, 0, 1, dstBuffer, bufferOffset);
+ t.queue.submit([encoder.finish()]);
+
+ const expectedBufferData = new Uint8Array(bufferSize);
+ await t.CheckGPUBufferContent(dstBuffer, bufferUsage, expectedBufferData);
+ });
+
+g.test('copy_texture_to_partial_buffer')
+ .desc(
+ `Verify when we copy from a GPUTexture into a GPUBuffer just after creating that GPUBuffer, the
+remaining part of it will be initialized to 0.`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('bufferOffset', [0, 8, -16])
+ .combine('arrayLayerCount', [1, 3])
+ .combine('copyMipLevel', [0, 2])
+ .combine('rowsPerImage', [16, 20])
+ .filter(t => {
+ // We don't need to test the copies that will cover the whole GPUBuffer.
+ return !(t.bufferOffset === 0 && t.rowsPerImage === 16);
+ })
+ )
+ .fn(async t => {
+ const { bufferOffset, arrayLayerCount, copyMipLevel, rowsPerImage } = t.params;
+ const srcTextureFormat = 'r8uint';
+ const textureSize = [32, 16, arrayLayerCount];
+
+ const srcTexture = t.device.createTexture({
+ format: srcTextureFormat,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ size: textureSize,
+ mipLevelCount: copyMipLevel + 1,
+ });
+ t.trackForCleanup(srcTexture);
+
+ const bytesPerRow = 256;
+ const layout = getTextureCopyLayout(srcTextureFormat, '2d', textureSize, {
+ mipLevel: copyMipLevel,
+ bytesPerRow,
+ rowsPerImage,
+ });
+
+ const dstBufferSize = layout.byteLength + Math.abs(bufferOffset);
+ const dstBuffer = t.device.createBuffer({
+ size: dstBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(dstBuffer);
+
+ const encoder = t.device.createCommandEncoder();
+
+ // Initialize srcTexture
+ for (let layer = 0; layer < arrayLayerCount; ++layer) {
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: srcTexture.createView({
+ baseArrayLayer: layer,
+ arrayLayerCount: 1,
+ baseMipLevel: copyMipLevel,
+ }),
+ clearValue: { r: layer + 1, g: 0, b: 0, a: 0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.end();
+ }
+
+ // Do texture-to-buffer copy
+ const appliedOffset = Math.max(bufferOffset, 0);
+ encoder.copyTextureToBuffer(
+ { texture: srcTexture, mipLevel: copyMipLevel },
+ { buffer: dstBuffer, offset: appliedOffset, bytesPerRow, rowsPerImage },
+ layout.mipSize
+ );
+
+ t.queue.submit([encoder.finish()]);
+
+ // Check if the contents of the destination buffer are what we expect.
+ const expectedData = new Uint8Array(dstBufferSize);
+ for (let layer = 0; layer < arrayLayerCount; ++layer) {
+ for (let y = 0; y < layout.mipSize[1]; ++y) {
+ for (let x = 0; x < layout.mipSize[0]; ++x) {
+ expectedData[appliedOffset + layer * bytesPerRow * rowsPerImage + y * bytesPerRow + x] =
+ layer + 1;
+ }
+ }
+ }
+ t.expectGPUBufferValuesEqual(dstBuffer, expectedData);
+ });
+
+g.test('uniform_buffer')
+ .desc(
+ `Verify when we use a GPUBuffer as a uniform buffer just after the creation of that GPUBuffer,
+ all the contents in that GPUBuffer have been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 256]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+
+ const boundBufferSize = 16;
+ const buffer = t.device.createBuffer({
+ size: bufferOffset + boundBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.UNIFORM,
+ });
+ t.trackForCleanup(buffer);
+
+ const computeShaderModule = t.device.createShaderModule({
+ code: `
+ struct UBO {
+ value : vec4<u32>
+ };
+ @group(0) @binding(0) var<uniform> ubo : UBO;
+ @group(0) @binding(1) var outImage : texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(1) fn main() {
+ if (all(ubo.value == vec4<u32>(0u, 0u, 0u, 0u))) {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(0.0, 1.0, 0.0, 1.0));
+ } else {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(1.0, 0.0, 0.0, 1.0));
+ }
+ }`,
+ });
+
+ // Verify the whole range of the buffer has been initialized to 0 in a compute shader.
+ t.TestBufferZeroInitInBindGroup(computeShaderModule, buffer, bufferOffset, boundBufferSize);
+ });
+
+g.test('readonly_storage_buffer')
+ .desc(
+ `Verify when we use a GPUBuffer as a read-only storage buffer just after the creation of that
+ GPUBuffer, all the contents in that GPUBuffer have been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 256]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+ const boundBufferSize = 16;
+ const buffer = t.device.createBuffer({
+ size: bufferOffset + boundBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+ t.trackForCleanup(buffer);
+
+ const computeShaderModule = t.device.createShaderModule({
+ code: `
+ struct SSBO {
+ value : vec4<u32>
+ };
+ @group(0) @binding(0) var<storage, read> ssbo : SSBO;
+ @group(0) @binding(1) var outImage : texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(1) fn main() {
+ if (all(ssbo.value == vec4<u32>(0u, 0u, 0u, 0u))) {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(0.0, 1.0, 0.0, 1.0));
+ } else {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(1.0, 0.0, 0.0, 1.0));
+ }
+ }`,
+ });
+
+ // Verify the whole range of the buffer has been initialized to 0 in a compute shader.
+ t.TestBufferZeroInitInBindGroup(computeShaderModule, buffer, bufferOffset, boundBufferSize);
+ });
+
+g.test('storage_buffer')
+ .desc(
+ `Verify when we use a GPUBuffer as a storage buffer just after the creation of that
+ GPUBuffer, all the contents in that GPUBuffer have been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 256]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+ const boundBufferSize = 16;
+ const buffer = t.device.createBuffer({
+ size: bufferOffset + boundBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+ t.trackForCleanup(buffer);
+
+ const computeShaderModule = t.device.createShaderModule({
+ code: `
+ struct SSBO {
+ value : vec4<u32>
+ };
+ @group(0) @binding(0) var<storage, read_write> ssbo : SSBO;
+ @group(0) @binding(1) var outImage : texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(1) fn main() {
+ if (all(ssbo.value == vec4<u32>(0u, 0u, 0u, 0u))) {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(0.0, 1.0, 0.0, 1.0));
+ } else {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(1.0, 0.0, 0.0, 1.0));
+ }
+ }`,
+ });
+
+ // Verify the whole range of the buffer has been initialized to 0 in a compute shader.
+ t.TestBufferZeroInitInBindGroup(computeShaderModule, buffer, bufferOffset, boundBufferSize);
+ });
+
+g.test('vertex_buffer')
+ .desc(
+ `Verify when we use a GPUBuffer as a vertex buffer just after the creation of that
+ GPUBuffer, all the contents in that GPUBuffer have been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 16]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+
+ const renderPipeline = t.CreateRenderPipelineForTest(
+ t.device.createShaderModule({
+ code: `
+ struct VertexOut {
+ @location(0) color : vec4<f32>,
+ @builtin(position) position : vec4<f32>,
+ };
+
+ @vertex fn main(@location(0) pos : vec4<f32>) -> VertexOut {
+ var output : VertexOut;
+ if (all(pos == vec4<f32>(0.0, 0.0, 0.0, 0.0))) {
+ output.color = vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ } else {
+ output.color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ output.position = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ return output;
+ }`,
+ }),
+ true
+ );
+
+ const bufferSize = 16 + bufferOffset;
+ const vertexBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(vertexBuffer);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(outputTexture);
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setVertexBuffer(0, vertexBuffer, bufferOffset);
+ renderPass.setPipeline(renderPipeline);
+ renderPass.draw(1);
+ renderPass.end();
+ t.queue.submit([encoder.finish()]);
+
+ t.CheckBufferAndOutputTexture(vertexBuffer, bufferSize, outputTexture);
+ });
+
+g.test('index_buffer')
+ .desc(
+ `Verify when we use a GPUBuffer as an index buffer just after the creation of that
+GPUBuffer, all the contents in that GPUBuffer have been initialized to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 16]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+
+ const renderPipeline = t.CreateRenderPipelineForTest(
+ t.device.createShaderModule({
+ code: `
+ struct VertexOut {
+ @location(0) color : vec4<f32>,
+ @builtin(position) position : vec4<f32>,
+ };
+
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOut {
+ var output : VertexOut;
+ if (VertexIndex == 0u) {
+ output.color = vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ } else {
+ output.color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }
+ output.position = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ return output;
+ }`,
+ }),
+ false
+ );
+
+ // The size of GPUBuffer must be at least 4.
+ const bufferSize = 4 + bufferOffset;
+ const indexBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(indexBuffer);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(outputTexture);
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(renderPipeline);
+ renderPass.setIndexBuffer(indexBuffer, 'uint16', bufferOffset, 4);
+ renderPass.drawIndexed(1);
+ renderPass.end();
+ t.queue.submit([encoder.finish()]);
+
+ t.CheckBufferAndOutputTexture(indexBuffer, bufferSize, outputTexture);
+ });
+
+g.test('indirect_buffer_for_draw_indirect')
+ .desc(
+ `Verify when we use a GPUBuffer as an indirect buffer for drawIndirect() or
+drawIndexedIndirect() just after the creation of that GPUBuffer, all the contents in that GPUBuffer
+have been initialized to 0.`
+ )
+ .params(u =>
+ u.combine('test_indexed_draw', [true, false]).beginSubcases().combine('bufferOffset', [0, 16])
+ )
+ .fn(async t => {
+ const { test_indexed_draw, bufferOffset } = t.params;
+
+ const renderPipeline = t.CreateRenderPipelineForTest(
+ t.device.createShaderModule({
+ code: `
+ struct VertexOut {
+ @location(0) color : vec4<f32>,
+ @builtin(position) position : vec4<f32>,
+ };
+
+ @vertex fn main() -> VertexOut {
+ var output : VertexOut;
+ output.color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ output.position = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ return output;
+ }`,
+ }),
+ false
+ );
+
+ const kDrawIndirectParametersSize = 16;
+ const kDrawIndexedIndirectParametersSize = 20;
+ const bufferSize =
+ Math.max(kDrawIndirectParametersSize, kDrawIndexedIndirectParametersSize) + bufferOffset;
+ const indirectBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.INDIRECT,
+ });
+ t.trackForCleanup(indirectBuffer);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(outputTexture);
+
+ // Initialize outputTexture to green.
+ const encoder = t.device.createCommandEncoder();
+ t.RecordInitializeTextureColor(encoder, outputTexture, { r: 0.0, g: 1.0, b: 0.0, a: 1.0 });
+
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPass.setPipeline(renderPipeline);
+
+ let indexBuffer = undefined;
+ if (test_indexed_draw) {
+ indexBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ t.trackForCleanup(indexBuffer);
+ renderPass.setIndexBuffer(indexBuffer, 'uint16');
+ renderPass.drawIndexedIndirect(indirectBuffer, bufferOffset);
+ } else {
+ renderPass.drawIndirect(indirectBuffer, bufferOffset);
+ }
+
+ renderPass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // The indirect buffer should be lazily cleared to 0, so we actually draw nothing and the color
+ // attachment will keep its original color (green) after we end the render pass.
+ t.CheckBufferAndOutputTexture(indirectBuffer, bufferSize, outputTexture);
+ });
+
+g.test('indirect_buffer_for_dispatch_indirect')
+ .desc(
+ `Verify when we use a GPUBuffer as an indirect buffer for dispatchWorkgroupsIndirect() just
+ after the creation of that GPUBuffer, all the contents in that GPUBuffer have been initialized
+ to 0.`
+ )
+ .paramsSubcasesOnly(u => u.combine('bufferOffset', [0, 16]))
+ .fn(async t => {
+ const { bufferOffset } = t.params;
+
+ const computePipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var outImage : texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(1) fn main() {
+ textureStore(outImage, vec2<i32>(0, 0), vec4<f32>(1.0, 0.0, 0.0, 1.0));
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const kDispatchIndirectParametersSize = 12;
+ const bufferSize = kDispatchIndirectParametersSize + bufferOffset;
+ const indirectBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.INDIRECT,
+ });
+ t.trackForCleanup(indirectBuffer);
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ GPUTextureUsage.RENDER_ATTACHMENT |
+ GPUTextureUsage.STORAGE_BINDING,
+ });
+ t.trackForCleanup(outputTexture);
+
+ // Initialize outputTexture to green.
+ const encoder = t.device.createCommandEncoder();
+ t.RecordInitializeTextureColor(encoder, outputTexture, { r: 0.0, g: 1.0, b: 0.0, a: 1.0 });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: outputTexture.createView(),
+ },
+ ],
+ });
+
+ // The indirect buffer should be lazily cleared to 0, so we actually don't execute the compute
+ // shader and the output texture should keep its original color (green).
+ const computePass = encoder.beginComputePass();
+ computePass.setBindGroup(0, bindGroup);
+ computePass.setPipeline(computePipeline);
+ computePass.dispatchWorkgroupsIndirect(indirectBuffer, bufferOffset);
+ computePass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // The indirect buffer should be lazily cleared to 0, so we actually draw nothing and the color
+ // attachment will keep its original color (green) after we end the compute pass.
+ t.CheckBufferAndOutputTexture(indirectBuffer, bufferSize, outputTexture);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js
new file mode 100644
index 0000000000..3f1eb766c8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_copy.js
@@ -0,0 +1,56 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../../../capability_info.js';
+import { virtualMipSize } from '../../../../util/texture/base.js';
+
+export const checkContentsByBufferCopy = (t, params, texture, state, subresourceRange) => {
+ for (const { level: mipLevel, layer } of subresourceRange.each()) {
+ assert(params.format in kTextureFormatInfo);
+ const format = params.format;
+
+ t.expectSingleColor(texture, format, {
+ size: [t.textureWidth, t.textureHeight, t.textureDepth],
+ dimension: params.dimension,
+ slice: layer,
+ layout: { mipLevel, aspect: params.aspect },
+ exp: t.stateToTexelComponents[state],
+ });
+ }
+};
+
+export const checkContentsByTextureCopy = (t, params, texture, state, subresourceRange) => {
+ for (const { level, layer } of subresourceRange.each()) {
+ assert(params.format in kTextureFormatInfo);
+ const format = params.format;
+
+ const [width, height, depth] = virtualMipSize(
+ params.dimension,
+ [t.textureWidth, t.textureHeight, t.textureDepth],
+ level
+ );
+
+ const dst = t.device.createTexture({
+ dimension: params.dimension,
+ size: [width, height, depth],
+ format: params.format,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+ t.trackForCleanup(dst);
+
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.copyTextureToTexture(
+ { texture, mipLevel: level, origin: { x: 0, y: 0, z: layer } },
+ { texture: dst, mipLevel: 0 },
+ { width, height, depthOrArrayLayers: depth }
+ );
+
+ t.queue.submit([commandEncoder.finish()]);
+
+ t.expectSingleColor(dst, format, {
+ size: [width, height, depth],
+ exp: t.stateToTexelComponents[state],
+ layout: { mipLevel: 0, aspect: params.aspect },
+ });
+ }
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js
new file mode 100644
index 0000000000..fb75af0f27
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_ds_test.js
@@ -0,0 +1,181 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../../../capability_info.js';
+import { virtualMipSize } from '../../../../util/texture/base.js';
+
+function makeFullscreenVertexModule(device) {
+ return device.createShaderModule({
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)
+ -> @builtin(position) vec4<f32> {
+ var pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-1.0, -3.0),
+ vec2<f32>( 3.0, 1.0),
+ vec2<f32>(-1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+ `,
+ });
+}
+
+function getDepthTestEqualPipeline(t, format, sampleCount, expected) {
+ return t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ entryPoint: 'main',
+ module: makeFullscreenVertexModule(t.device),
+ },
+ fragment: {
+ entryPoint: 'main',
+ module: t.device.createShaderModule({
+ code: `
+ struct Outputs {
+ @builtin(frag_depth) FragDepth : f32,
+ @location(0) outSuccess : f32,
+ };
+
+ @fragment
+ fn main() -> Outputs {
+ var output : Outputs;
+ output.FragDepth = f32(${expected});
+ output.outSuccess = 1.0;
+ return output;
+ }
+ `,
+ }),
+ targets: [{ format: 'r8unorm' }],
+ },
+ depthStencil: {
+ format,
+ depthCompare: 'equal',
+ },
+ primitive: { topology: 'triangle-list' },
+ multisample: { count: sampleCount },
+ });
+}
+
+function getStencilTestEqualPipeline(t, format, sampleCount) {
+ return t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ entryPoint: 'main',
+ module: makeFullscreenVertexModule(t.device),
+ },
+ fragment: {
+ entryPoint: 'main',
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) f32 {
+ return 1.0;
+ }
+ `,
+ }),
+ targets: [{ format: 'r8unorm' }],
+ },
+ depthStencil: {
+ format,
+ stencilFront: { compare: 'equal' },
+ stencilBack: { compare: 'equal' },
+ },
+ primitive: { topology: 'triangle-list' },
+ multisample: { count: sampleCount },
+ });
+}
+
+const checkContents = (type, t, params, texture, state, subresourceRange) => {
+ const formatInfo = kTextureFormatInfo[params.format];
+
+ assert(params.dimension === '2d');
+ for (const viewDescriptor of t.generateTextureViewDescriptorsForRendering(
+ 'all',
+ subresourceRange
+ )) {
+ assert(viewDescriptor.baseMipLevel !== undefined);
+ const [width, height] = virtualMipSize(
+ params.dimension,
+ [t.textureWidth, t.textureHeight, 1],
+ viewDescriptor.baseMipLevel
+ );
+
+ const renderTexture = t.device.createTexture({
+ size: [width, height, 1],
+ format: 'r8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ sampleCount: params.sampleCount,
+ });
+
+ let resolveTexture = undefined;
+ let resolveTarget = undefined;
+ if (params.sampleCount > 1) {
+ resolveTexture = t.device.createTexture({
+ size: [width, height, 1],
+ format: 'r8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ resolveTarget = resolveTexture.createView();
+ }
+
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.pushDebugGroup('checkContentsWithDepthStencil');
+
+ const pass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTexture.createView(),
+ resolveTarget,
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment: {
+ view: texture.createView(viewDescriptor),
+ depthStoreOp: formatInfo.depth ? 'store' : undefined,
+ depthLoadOp: formatInfo.depth ? 'load' : undefined,
+ stencilStoreOp: formatInfo.stencil ? 'store' : undefined,
+ stencilLoadOp: formatInfo.stencil ? 'load' : undefined,
+ },
+ });
+
+ switch (type) {
+ case 'depth': {
+ const expectedDepth = t.stateToTexelComponents[state].Depth;
+ assert(expectedDepth !== undefined);
+
+ pass.setPipeline(
+ getDepthTestEqualPipeline(t, params.format, params.sampleCount, expectedDepth)
+ );
+
+ break;
+ }
+
+ case 'stencil': {
+ const expectedStencil = t.stateToTexelComponents[state].Stencil;
+ assert(expectedStencil !== undefined);
+
+ pass.setPipeline(getStencilTestEqualPipeline(t, params.format, params.sampleCount));
+ pass.setStencilReference(expectedStencil);
+ break;
+ }
+ }
+
+ pass.draw(3);
+ pass.end();
+
+ commandEncoder.popDebugGroup();
+ t.queue.submit([commandEncoder.finish()]);
+
+ t.expectSingleColor(resolveTexture || renderTexture, 'r8unorm', {
+ size: [width, height, 1],
+ exp: { R: 1 },
+ });
+ }
+};
+
+export const checkContentsByDepthTest = (...args) => checkContents('depth', ...args);
+
+export const checkContentsByStencilTest = (...args) => checkContents('stencil', ...args);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js
new file mode 100644
index 0000000000..c7cc5fd9af
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/check_texture/by_sampling.js
@@ -0,0 +1,152 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../../../capability_info.js';
+import { virtualMipSize } from '../../../../util/texture/base.js';
+import {
+ kTexelRepresentationInfo,
+ getSingleDataType,
+ getComponentReadbackTraits,
+} from '../../../../util/texture/texel_data.js';
+
+export const checkContentsBySampling = (t, params, texture, state, subresourceRange) => {
+ assert(params.format in kTextureFormatInfo);
+ const format = params.format;
+ const rep = kTexelRepresentationInfo[format];
+
+ for (const { level, layers } of subresourceRange.mipLevels()) {
+ const [width, height, depth] = virtualMipSize(
+ params.dimension,
+ [t.textureWidth, t.textureHeight, t.textureDepth],
+ level
+ );
+
+ const { ReadbackTypedArray, shaderType } = getComponentReadbackTraits(
+ getSingleDataType(format)
+ );
+
+ const componentOrder = rep.componentOrder;
+ const componentCount = componentOrder.length;
+
+ // For single-component textures, generates .r
+ // For multi-component textures, generates ex.)
+ // .rgba[i], .bgra[i], .rgb[i]
+ const indexExpression =
+ componentCount === 1
+ ? componentOrder[0].toLowerCase()
+ : componentOrder.map(c => c.toLowerCase()).join('') + '[i]';
+
+ const _xd = '_' + params.dimension;
+ const _multisampled = params.sampleCount > 1 ? '_multisampled' : '';
+ const texelIndexExpression =
+ params.dimension === '2d'
+ ? 'vec2<i32>(GlobalInvocationID.xy)'
+ : params.dimension === '3d'
+ ? 'vec3<i32>(GlobalInvocationID.xyz)'
+ : params.dimension === '1d'
+ ? 'i32(GlobalInvocationID.x)'
+ : unreachable();
+ const computePipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ entryPoint: 'main',
+ module: t.device.createShaderModule({
+ code: `
+ struct Constants {
+ level : i32
+ };
+
+ @group(0) @binding(0) var<uniform> constants : Constants;
+ @group(0) @binding(1) var myTexture : texture${_multisampled}${_xd}<${shaderType}>;
+
+ struct Result {
+ values : array<${shaderType}>
+ };
+ @group(0) @binding(3) var<storage, read_write> result : Result;
+
+ @compute @workgroup_size(1)
+ fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {
+ let flatIndex : u32 = ${componentCount}u * (
+ ${width}u * ${height}u * GlobalInvocationID.z +
+ ${width}u * GlobalInvocationID.y +
+ GlobalInvocationID.x
+ );
+ let texel : vec4<${shaderType}> = textureLoad(
+ myTexture, ${texelIndexExpression}, constants.level);
+
+ for (var i : u32 = 0u; i < ${componentCount}u; i = i + 1u) {
+ result.values[flatIndex + i] = texel.${indexExpression};
+ }
+ }`,
+ }),
+ },
+ });
+
+ for (const layer of layers) {
+ const ubo = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: 4,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+ new Int32Array(ubo.getMappedRange(), 0, 1)[0] = level;
+ ubo.unmap();
+
+ const byteLength =
+ width * height * depth * ReadbackTypedArray.BYTES_PER_ELEMENT * rep.componentOrder.length;
+ const resultBuffer = t.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(resultBuffer);
+
+ const bindGroup = t.device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: ubo },
+ },
+ {
+ binding: 1,
+ resource: texture.createView({
+ baseArrayLayer: layer,
+ arrayLayerCount: 1,
+ dimension: params.dimension,
+ }),
+ },
+ {
+ binding: 3,
+ resource: {
+ buffer: resultBuffer,
+ },
+ },
+ ],
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const pass = commandEncoder.beginComputePass();
+ pass.setPipeline(computePipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(width, height, depth);
+ pass.end();
+ t.queue.submit([commandEncoder.finish()]);
+ ubo.destroy();
+
+ const expectedValues = new ReadbackTypedArray(new ArrayBuffer(byteLength));
+ const expectedState = t.stateToTexelComponents[state];
+ let i = 0;
+ for (let d = 0; d < depth; ++d) {
+ for (let h = 0; h < height; ++h) {
+ for (let w = 0; w < width; ++w) {
+ for (const c of rep.componentOrder) {
+ const value = expectedState[c];
+ assert(value !== undefined);
+ expectedValues[i++] = value;
+ }
+ }
+ }
+ }
+ t.expectGPUBufferValuesEqual(resultBuffer, expectedValues);
+ }
+ }
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js
new file mode 100644
index 0000000000..eab85d8236
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/resource_init/texture_zero.spec.js
@@ -0,0 +1,614 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test uninitialized textures are initialized to zero when read.
+
+TODO:
+- test by sampling depth/stencil [1]
+- test by copying out of stencil [2]
+- test compressed texture formats [3]
+`; // MAINTENANCE_TODO: This is a test file, it probably shouldn't export anything.
+// Everything that's exported should be moved to another file.
+
+import { kUnitCaseParamsBuilder } from '../../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kTextureAspects,
+ kUncompressedTextureFormats,
+ textureDimensionAndFormatCompatible,
+ kTextureDimensions,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { virtualMipSize } from '../../../util/texture/base.js';
+import { createTextureUploadBuffer } from '../../../util/texture/layout.js';
+import { SubresourceRange } from '../../../util/texture/subresource.js';
+import { kTexelRepresentationInfo } from '../../../util/texture/texel_data.js';
+
+export let UninitializeMethod;
+
+// The texture was rendered to with GPUStoreOp "clear"
+(function (UninitializeMethod) {
+ UninitializeMethod['Creation'] = 'Creation';
+ UninitializeMethod['StoreOpClear'] = 'StoreOpClear';
+})(UninitializeMethod || (UninitializeMethod = {}));
+const kUninitializeMethods = Object.keys(UninitializeMethod);
+
+export let ReadMethod;
+
+// Read the texture as a storage texture
+
+// Test with these mip level counts
+(function (ReadMethod) {
+ ReadMethod['Sample'] = 'Sample';
+ ReadMethod['CopyToBuffer'] = 'CopyToBuffer';
+ ReadMethod['CopyToTexture'] = 'CopyToTexture';
+ ReadMethod['DepthTest'] = 'DepthTest';
+ ReadMethod['StencilTest'] = 'StencilTest';
+ ReadMethod['ColorBlending'] = 'ColorBlending';
+ ReadMethod['Storage'] = 'Storage';
+})(ReadMethod || (ReadMethod = {}));
+const kMipLevelCounts = [1, 5];
+
+// For each mip level count, define the mip ranges to leave uninitialized.
+const kUninitializedMipRangesToTest = {
+ 1: [{ begin: 0, end: 1 }], // Test the only mip
+ 5: [
+ { begin: 0, end: 2 },
+ { begin: 3, end: 4 },
+ ],
+ // Test a range and a single mip
+};
+
+// Test with these sample counts.
+const kSampleCounts = [1, 4];
+
+// Test with these layer counts.
+
+// For each layer count, define the layers to leave uninitialized.
+const kUninitializedLayerRangesToTest = {
+ 1: [{ begin: 0, end: 1 }], // Test the only layer
+ 7: [
+ { begin: 2, end: 4 },
+ { begin: 6, end: 7 },
+ ],
+ // Test a range and a single layer
+};
+
+// Enums to abstract over color / depth / stencil values in textures. Depending on the texture format,
+// the data for each value may have a different representation. These enums are converted to a
+// representation such that their values can be compared. ex.) An integer is needed to upload to an
+// unsigned normalized format, but its value is read as a float in the shader.
+export let InitializedState;
+
+// We check that uninitialized subresources are in this state when read back.
+(function (InitializedState) {
+ InitializedState[(InitializedState['Canary'] = 0)] = 'Canary';
+ InitializedState[(InitializedState['Zero'] = 1)] = 'Zero';
+})(InitializedState || (InitializedState = {}));
+
+const initializedStateAsFloat = {
+ [InitializedState.Zero]: 0,
+ [InitializedState.Canary]: 1,
+};
+
+const initializedStateAsUint = {
+ [InitializedState.Zero]: 0,
+ [InitializedState.Canary]: 1,
+};
+
+const initializedStateAsSint = {
+ [InitializedState.Zero]: 0,
+ [InitializedState.Canary]: -1,
+};
+
+function initializedStateAsColor(state, format) {
+ let value;
+ if (format.indexOf('uint') !== -1) {
+ value = initializedStateAsUint[state];
+ } else if (format.indexOf('sint') !== -1) {
+ value = initializedStateAsSint[state];
+ } else {
+ value = initializedStateAsFloat[state];
+ }
+ return [value, value, value, value];
+}
+
+const initializedStateAsDepth = {
+ [InitializedState.Zero]: 0,
+ [InitializedState.Canary]: 0.8,
+};
+
+const initializedStateAsStencil = {
+ [InitializedState.Zero]: 0,
+ [InitializedState.Canary]: 42,
+};
+
+function getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod) {
+ let usage = GPUConst.TextureUsage.COPY_DST;
+
+ switch (uninitializeMethod) {
+ case UninitializeMethod.Creation:
+ break;
+ case UninitializeMethod.StoreOpClear:
+ usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT;
+ break;
+ default:
+ unreachable();
+ }
+
+ switch (readMethod) {
+ case ReadMethod.CopyToBuffer:
+ case ReadMethod.CopyToTexture:
+ usage |= GPUConst.TextureUsage.COPY_SRC;
+ break;
+ case ReadMethod.Sample:
+ usage |= GPUConst.TextureUsage.TEXTURE_BINDING;
+ break;
+ case ReadMethod.Storage:
+ usage |= GPUConst.TextureUsage.STORAGE_BINDING;
+ break;
+ case ReadMethod.DepthTest:
+ case ReadMethod.StencilTest:
+ case ReadMethod.ColorBlending:
+ usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT;
+ break;
+ default:
+ unreachable();
+ }
+
+ if (sampleCount > 1) {
+ // Copies to multisampled textures are not allowed. We need OutputAttachment to initialize
+ // canary data in multisampled textures.
+ usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT;
+ }
+
+ if (!kTextureFormatInfo[format].copyDst) {
+ // Copies are not possible. We need OutputAttachment to initialize
+ // canary data.
+ assert(kTextureFormatInfo[format].renderable);
+ usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT;
+ }
+
+ return usage;
+}
+
+export class TextureZeroInitTest extends GPUTest {
+ constructor(sharedState, rec, params) {
+ super(sharedState, rec, params);
+ this.p = params;
+
+ const stateToTexelComponents = state => {
+ const [R, G, B, A] = initializedStateAsColor(state, this.p.format);
+ return {
+ R,
+ G,
+ B,
+ A,
+ Depth: initializedStateAsDepth[state],
+ Stencil: initializedStateAsStencil[state],
+ };
+ };
+
+ this.stateToTexelComponents = {
+ [InitializedState.Zero]: stateToTexelComponents(InitializedState.Zero),
+ [InitializedState.Canary]: stateToTexelComponents(InitializedState.Canary),
+ };
+ }
+
+ get textureWidth() {
+ let width = 1 << this.p.mipLevelCount;
+ if (this.p.nonPowerOfTwo) {
+ width = 2 * width - 1;
+ }
+ return width;
+ }
+
+ get textureHeight() {
+ if (this.p.dimension === '1d') {
+ return 1;
+ }
+
+ let height = 1 << this.p.mipLevelCount;
+ if (this.p.nonPowerOfTwo) {
+ height = 2 * height - 1;
+ }
+ return height;
+ }
+
+ get textureDepth() {
+ return this.p.dimension === '3d' ? 11 : 1;
+ }
+
+ get textureDepthOrArrayLayers() {
+ return this.p.dimension === '2d' ? this.p.layerCount : this.textureDepth;
+ }
+
+ // Used to iterate subresources and check that their uninitialized contents are zero when accessed
+ *iterateUninitializedSubresources() {
+ for (const mipRange of kUninitializedMipRangesToTest[this.p.mipLevelCount]) {
+ for (const layerRange of kUninitializedLayerRangesToTest[this.p.layerCount]) {
+ yield new SubresourceRange({ mipRange, layerRange });
+ }
+ }
+ }
+
+ // Used to iterate and initialize other subresources not checked for zero-initialization.
+ // Zero-initialization of uninitialized subresources should not have side effects on already
+ // initialized subresources.
+ *iterateInitializedSubresources() {
+ const uninitialized = new Array(this.p.mipLevelCount);
+ for (let level = 0; level < uninitialized.length; ++level) {
+ uninitialized[level] = new Array(this.p.layerCount);
+ }
+ for (const subresources of this.iterateUninitializedSubresources()) {
+ for (const { level, layer } of subresources.each()) {
+ uninitialized[level][layer] = true;
+ }
+ }
+ for (let level = 0; level < uninitialized.length; ++level) {
+ for (let layer = 0; layer < uninitialized[level].length; ++layer) {
+ if (!uninitialized[level][layer]) {
+ yield new SubresourceRange({
+ mipRange: { begin: level, count: 1 },
+ layerRange: { begin: layer, count: 1 },
+ });
+ }
+ }
+ }
+ }
+
+ *generateTextureViewDescriptorsForRendering(aspect, subresourceRange) {
+ const viewDescriptor = {
+ dimension: '2d',
+ aspect,
+ };
+
+ if (subresourceRange === undefined) {
+ return viewDescriptor;
+ }
+
+ for (const { level, layer } of subresourceRange.each()) {
+ yield {
+ ...viewDescriptor,
+ baseMipLevel: level,
+ mipLevelCount: 1,
+ baseArrayLayer: layer,
+ arrayLayerCount: 1,
+ };
+ }
+ }
+
+ initializeWithStoreOp(state, texture, subresourceRange) {
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.pushDebugGroup('initializeWithStoreOp');
+
+ for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering(
+ 'all',
+ subresourceRange
+ )) {
+ if (kTextureFormatInfo[this.p.format].color) {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [
+ {
+ view: texture.createView(viewDescriptor),
+ storeOp: 'store',
+ clearValue: initializedStateAsColor(state, this.p.format),
+ loadOp: 'clear',
+ },
+ ],
+ })
+ .end();
+ } else {
+ const depthStencilAttachment = {
+ view: texture.createView(viewDescriptor),
+ };
+ if (kTextureFormatInfo[this.p.format].depth) {
+ depthStencilAttachment.depthClearValue = initializedStateAsDepth[state];
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'store';
+ }
+ if (kTextureFormatInfo[this.p.format].stencil) {
+ depthStencilAttachment.stencilClearValue = initializedStateAsStencil[state];
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment,
+ })
+ .end();
+ }
+ }
+
+ commandEncoder.popDebugGroup();
+ this.queue.submit([commandEncoder.finish()]);
+ }
+
+ initializeWithCopy(texture, state, subresourceRange) {
+ assert(this.p.format in kTextureFormatInfo);
+ const format = this.p.format;
+
+ const firstSubresource = subresourceRange.each().next().value;
+ assert(typeof firstSubresource !== 'undefined');
+
+ const [largestWidth, largestHeight, largestDepth] = virtualMipSize(
+ this.p.dimension,
+ [this.textureWidth, this.textureHeight, this.textureDepth],
+ firstSubresource.level
+ );
+
+ const rep = kTexelRepresentationInfo[format];
+ const texelData = new Uint8Array(rep.pack(rep.encode(this.stateToTexelComponents[state])));
+ const { buffer, bytesPerRow, rowsPerImage } = createTextureUploadBuffer(
+ texelData,
+ this.device,
+ format,
+ this.p.dimension,
+ [largestWidth, largestHeight, largestDepth]
+ );
+
+ const commandEncoder = this.device.createCommandEncoder();
+
+ for (const { level, layer } of subresourceRange.each()) {
+ const [width, height, depth] = virtualMipSize(
+ this.p.dimension,
+ [this.textureWidth, this.textureHeight, this.textureDepth],
+ level
+ );
+
+ commandEncoder.copyBufferToTexture(
+ {
+ buffer,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ { texture, mipLevel: level, origin: { x: 0, y: 0, z: layer } },
+ { width, height, depthOrArrayLayers: depth }
+ );
+ }
+ this.queue.submit([commandEncoder.finish()]);
+ buffer.destroy();
+ }
+
+ initializeTexture(texture, state, subresourceRange) {
+ if (this.p.sampleCount > 1 || !kTextureFormatInfo[this.p.format].copyDst) {
+ // Copies to multisampled textures not yet specified.
+ // Use a storeOp for now.
+ assert(kTextureFormatInfo[this.p.format].renderable);
+ this.initializeWithStoreOp(state, texture, subresourceRange);
+ } else {
+ this.initializeWithCopy(texture, state, subresourceRange);
+ }
+ }
+
+ discardTexture(texture, subresourceRange) {
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.pushDebugGroup('discardTexture');
+
+ for (const desc of this.generateTextureViewDescriptorsForRendering('all', subresourceRange)) {
+ if (kTextureFormatInfo[this.p.format].color) {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [
+ {
+ view: texture.createView(desc),
+ storeOp: 'discard',
+ loadOp: 'load',
+ },
+ ],
+ })
+ .end();
+ } else {
+ const depthStencilAttachment = {
+ view: texture.createView(desc),
+ };
+ if (kTextureFormatInfo[this.p.format].depth) {
+ depthStencilAttachment.depthLoadOp = 'load';
+ depthStencilAttachment.depthStoreOp = 'discard';
+ }
+ if (kTextureFormatInfo[this.p.format].stencil) {
+ depthStencilAttachment.stencilLoadOp = 'load';
+ depthStencilAttachment.stencilStoreOp = 'discard';
+ }
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment,
+ })
+ .end();
+ }
+ }
+
+ commandEncoder.popDebugGroup();
+ this.queue.submit([commandEncoder.finish()]);
+ }
+}
+
+const kTestParams = kUnitCaseParamsBuilder
+ .combine('dimension', kTextureDimensions)
+ .combine('readMethod', [
+ ReadMethod.CopyToBuffer,
+ ReadMethod.CopyToTexture,
+ ReadMethod.Sample,
+ ReadMethod.DepthTest,
+ ReadMethod.StencilTest,
+ ])
+
+ // [3] compressed formats
+ .combine('format', kUncompressedTextureFormats)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('aspect', kTextureAspects)
+ .unless(({ readMethod, format, aspect }) => {
+ const info = kTextureFormatInfo[format];
+ return (
+ (readMethod === ReadMethod.DepthTest && (!info.depth || aspect === 'stencil-only')) ||
+ (readMethod === ReadMethod.StencilTest && (!info.stencil || aspect === 'depth-only')) ||
+ (readMethod === ReadMethod.ColorBlending && !info.color) ||
+ // [1]: Test with depth/stencil sampling
+ (readMethod === ReadMethod.Sample && (info.depth || info.stencil)) ||
+ (aspect === 'depth-only' && !info.depth) ||
+ (aspect === 'stencil-only' && !info.stencil) ||
+ (aspect === 'all' && info.depth && info.stencil) ||
+ // Cannot copy from a packed depth format.
+ // [2]: Test copying out of the stencil aspect.
+ ((readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) &&
+ (format === 'depth24plus' || format === 'depth24plus-stencil8'))
+ );
+ })
+ .combine('mipLevelCount', kMipLevelCounts)
+ // 1D texture can only have a single mip level
+ .unless(p => p.dimension === '1d' && p.mipLevelCount !== 1)
+ .combine('sampleCount', kSampleCounts)
+ .unless(
+ ({ readMethod, sampleCount }) =>
+ // We can only read from multisampled textures by sampling.
+ sampleCount > 1 &&
+ (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture)
+ )
+
+ // Multisampled textures may only have one mip
+ .unless(({ sampleCount, mipLevelCount }) => sampleCount > 1 && mipLevelCount > 1)
+ .combine('uninitializeMethod', kUninitializeMethods)
+ .unless(({ dimension, readMethod, uninitializeMethod, format, sampleCount }) => {
+ const formatInfo = kTextureFormatInfo[format];
+ return (
+ dimension !== '2d' &&
+ (sampleCount > 1 ||
+ formatInfo.depth ||
+ formatInfo.stencil ||
+ readMethod === ReadMethod.DepthTest ||
+ readMethod === ReadMethod.StencilTest ||
+ readMethod === ReadMethod.ColorBlending ||
+ uninitializeMethod === UninitializeMethod.StoreOpClear)
+ );
+ })
+ .expandWithParams(function* ({ dimension }) {
+ switch (dimension) {
+ case '2d':
+ yield { layerCount: 1 };
+ yield { layerCount: 7 };
+ break;
+ case '1d':
+ case '3d':
+ yield { layerCount: 1 };
+ break;
+ }
+ })
+ // Multisampled 3D / 2D array textures not supported.
+ .unless(({ sampleCount, layerCount }) => sampleCount > 1 && layerCount > 1)
+ .unless(({ format, sampleCount, uninitializeMethod, readMethod }) => {
+ const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod);
+ const info = kTextureFormatInfo[format];
+
+ return (
+ ((usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 && !info.renderable) ||
+ ((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !info.storage) ||
+ (sampleCount > 1 && !info.multisample)
+ );
+ })
+ .combine('nonPowerOfTwo', [false, true])
+ .combine('canaryOnCreation', [false, true])
+ .filter(({ canaryOnCreation, format }) => {
+ // We can only initialize the texture if it's encodable or renderable.
+ const canInitialize = format in kTextureFormatInfo || kTextureFormatInfo[format].renderable;
+
+ // Filter out cases where we want canary values but can't initialize.
+ return !canaryOnCreation || canInitialize;
+ });
+
+import { checkContentsByBufferCopy, checkContentsByTextureCopy } from './check_texture/by_copy.js';
+import {
+ checkContentsByDepthTest,
+ checkContentsByStencilTest,
+} from './check_texture/by_ds_test.js';
+import { checkContentsBySampling } from './check_texture/by_sampling.js';
+
+const checkContentsImpl = {
+ Sample: checkContentsBySampling,
+ CopyToBuffer: checkContentsByBufferCopy,
+ CopyToTexture: checkContentsByTextureCopy,
+ DepthTest: checkContentsByDepthTest,
+ StencilTest: checkContentsByStencilTest,
+ ColorBlending: t => t.skip('Not implemented'),
+ Storage: t => t.skip('Not implemented'),
+};
+
+export const g = makeTestGroup(TextureZeroInitTest);
+
+g.test('uninitialized_texture_is_zero')
+ .params(kTestParams)
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[t.params.format].feature);
+ })
+ .fn(async t => {
+ const usage = getRequiredTextureUsage(
+ t.params.format,
+ t.params.sampleCount,
+ t.params.uninitializeMethod,
+ t.params.readMethod
+ );
+
+ const texture = t.device.createTexture({
+ size: [t.textureWidth, t.textureHeight, t.textureDepthOrArrayLayers],
+ format: t.params.format,
+ dimension: t.params.dimension,
+ usage,
+ mipLevelCount: t.params.mipLevelCount,
+ sampleCount: t.params.sampleCount,
+ });
+ t.trackForCleanup(texture);
+
+ if (t.params.canaryOnCreation) {
+ // Initialize some subresources with canary values
+ for (const subresourceRange of t.iterateInitializedSubresources()) {
+ t.initializeTexture(texture, InitializedState.Canary, subresourceRange);
+ }
+ }
+
+ switch (t.params.uninitializeMethod) {
+ case UninitializeMethod.Creation:
+ break;
+ case UninitializeMethod.StoreOpClear:
+ // Initialize the rest of the resources.
+ for (const subresourceRange of t.iterateUninitializedSubresources()) {
+ t.initializeTexture(texture, InitializedState.Canary, subresourceRange);
+ }
+ // Then use a store op to discard their contents.
+ for (const subresourceRange of t.iterateUninitializedSubresources()) {
+ t.discardTexture(texture, subresourceRange);
+ }
+ break;
+ default:
+ unreachable();
+ }
+
+ // Check that all uninitialized resources are zero.
+ for (const subresourceRange of t.iterateUninitializedSubresources()) {
+ checkContentsImpl[t.params.readMethod](
+ t,
+ t.params,
+ texture,
+ InitializedState.Zero,
+ subresourceRange
+ );
+ }
+
+ if (t.params.canaryOnCreation) {
+ // Check the all other resources are unchanged.
+ for (const subresourceRange of t.iterateInitializedSubresources()) {
+ checkContentsImpl[t.params.readMethod](
+ t,
+ t.params,
+ texture,
+ InitializedState.Canary,
+ subresourceRange
+ );
+ }
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/anisotropy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/anisotropy.spec.js
new file mode 100644
index 0000000000..36315f9d69
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/anisotropy.spec.js
@@ -0,0 +1,326 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests the behavior of anisotropic filtering.
+
+TODO:
+Note that anisotropic filtering is never guaranteed to occur, but we might be able to test some
+things. If there are no guarantees we can issue warnings instead of failures. Ideas:
+ - No *more* than the provided maxAnisotropy samples are used, by testing how many unique
+ sample values come out of the sample operation.
+ - Check anisotropy is done in the correct direction (by having a 2D gradient and checking we get
+ more of the color in the correct direction).
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsEqual } from '../../../util/check_contents.js';
+
+const kRTSize = 16;
+const kBytesPerRow = 256;
+const xMiddle = kRTSize / 2; // we check the pixel value in the middle of the render target
+const kColorAttachmentFormat = 'rgba8unorm';
+const kTextureFormat = 'rgba8unorm';
+const colors = [
+ new Uint8Array([0xff, 0x00, 0x00, 0xff]), // miplevel = 0
+ new Uint8Array([0x00, 0xff, 0x00, 0xff]), // miplevel = 1
+ new Uint8Array([0x00, 0x00, 0xff, 0xff]), // miplevel = 2
+];
+const checkerColors = [
+ new Uint8Array([0xff, 0x00, 0x00, 0xff]),
+ new Uint8Array([0x00, 0xff, 0x00, 0xff]),
+];
+
+// renders texture a slanted plane placed in a specific way
+class SamplerAnisotropicFilteringSlantedPlaneTest extends GPUTest {
+ copyRenderTargetToBuffer(rt) {
+ const byteLength = kRTSize * kBytesPerRow;
+ const buffer = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToBuffer(
+ { texture: rt, mipLevel: 0, origin: [0, 0, 0] },
+ { buffer, bytesPerRow: kBytesPerRow, rowsPerImage: kRTSize },
+ { width: kRTSize, height: kRTSize, depthOrArrayLayers: 1 }
+ );
+
+ this.queue.submit([commandEncoder.finish()]);
+
+ return buffer;
+ }
+
+ async init() {
+ await super.init();
+
+ this.pipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Outputs {
+ @builtin(position) Position : vec4<f32>,
+ @location(0) fragUV : vec2<f32>,
+ };
+
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32) -> Outputs {
+ var position : array<vec3<f32>, 6> = array<vec3<f32>, 6>(
+ vec3<f32>(-0.5, 0.5, -0.5),
+ vec3<f32>(0.5, 0.5, -0.5),
+ vec3<f32>(-0.5, 0.5, 0.5),
+ vec3<f32>(-0.5, 0.5, 0.5),
+ vec3<f32>(0.5, 0.5, -0.5),
+ vec3<f32>(0.5, 0.5, 0.5));
+ // uv is pre-scaled to mimic repeating tiled texture
+ var uv : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(0.0, 0.0),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(0.0, 50.0),
+ vec2<f32>(0.0, 50.0),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(1.0, 50.0));
+ // draw a slanted plane in a specific way
+ let matrix : mat4x4<f32> = mat4x4<f32>(
+ vec4<f32>(-1.7320507764816284, 1.8322050568049563e-16, -6.176817699518044e-17, -6.170640314703498e-17),
+ vec4<f32>(-2.1211504944260596e-16, -1.496108889579773, 0.5043753981590271, 0.5038710236549377),
+ vec4<f32>(0.0, -43.63650894165039, -43.232173919677734, -43.18894577026367),
+ vec4<f32>(0.0, 21.693578720092773, 21.789791107177734, 21.86800193786621));
+
+ var output : Outputs;
+ output.fragUV = uv[VertexIndex];
+ output.Position = matrix * vec4<f32>(position[VertexIndex], 1.0);
+ return output;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var sampler0 : sampler;
+ @group(0) @binding(1) var texture0 : texture_2d<f32>;
+
+ @fragment fn main(
+ @builtin(position) FragCoord : vec4<f32>,
+ @location(0) fragUV: vec2<f32>)
+ -> @location(0) vec4<f32> {
+ return textureSample(texture0, sampler0, fragUV);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ }
+
+ // return the render target texture object
+ drawSlantedPlane(textureView, sampler) {
+ // make sure it's already initialized
+ assert(this.pipeline !== undefined);
+
+ const bindGroup = this.device.createBindGroup({
+ entries: [
+ { binding: 0, resource: sampler },
+ { binding: 1, resource: textureView },
+ ],
+
+ layout: this.pipeline.getBindGroupLayout(0),
+ });
+
+ const colorAttachment = this.device.createTexture({
+ format: kColorAttachmentFormat,
+ size: { width: kRTSize, height: kRTSize, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(this.pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.draw(6);
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ return colorAttachment;
+ }
+}
+
+export const g = makeTestGroup(SamplerAnisotropicFilteringSlantedPlaneTest);
+
+g.test('anisotropic_filter_checkerboard')
+ .desc(
+ `Anisotropic filter rendering tests that draws a slanted plane and samples from a texture
+ that only has a top level mipmap, the content of which is like a checkerboard.
+ We will check the rendering result using sampler with maxAnisotropy values to be
+ different from each other, as the sampling rate is different.
+ We will also check if those large maxAnisotropy values are clamped so that rendering is the
+ same as the supported upper limit say 16.
+ A similar webgl demo is at https://jsfiddle.net/yqnbez24`
+ )
+ .fn(async t => {
+ // init texture with only a top level mipmap
+ const textureSize = 32;
+ const texture = t.device.createTexture({
+ mipLevelCount: 1,
+ size: { width: textureSize, height: textureSize, depthOrArrayLayers: 1 },
+ format: kTextureFormat,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ const textureEncoder = t.device.createCommandEncoder();
+
+ const bufferSize = kBytesPerRow * textureSize; // RGBA8 for each pixel (256 > 16 * 4)
+
+ // init checkerboard texture data
+ const data = new Uint8Array(bufferSize);
+ for (let r = 0; r < textureSize; r++) {
+ const o = r * kBytesPerRow;
+ for (let c = o, end = o + textureSize * 4; c < end; c += 4) {
+ const cid = (r + (c - o) / 4) % 2;
+ const color = checkerColors[cid];
+ data[c] = color[0];
+ data[c + 1] = color[1];
+ data[c + 2] = color[2];
+ data[c + 3] = color[3];
+ }
+ }
+ const buffer = t.makeBufferWithContents(
+ data,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ const bytesPerRow = kBytesPerRow;
+ const rowsPerImage = textureSize;
+
+ textureEncoder.copyBufferToTexture(
+ {
+ buffer,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ {
+ texture,
+ mipLevel: 0,
+ origin: [0, 0, 0],
+ },
+ [textureSize, textureSize, 1]
+ );
+
+ t.device.queue.submit([textureEncoder.finish()]);
+
+ const textureView = texture.createView();
+ const byteLength = kRTSize * kBytesPerRow;
+ const results = [];
+
+ for (const maxAnisotropy of [1, 16, 1024]) {
+ const sampler = t.device.createSampler({
+ magFilter: 'linear',
+ minFilter: 'linear',
+ mipmapFilter: 'linear',
+ maxAnisotropy,
+ });
+ const result = await t.readGPUBufferRangeTyped(
+ t.copyRenderTargetToBuffer(t.drawSlantedPlane(textureView, sampler)),
+ { type: Uint8Array, typedLength: byteLength }
+ );
+
+ results.push(result);
+ }
+
+ const check0 = checkElementsEqual(results[0].data, results[1].data);
+ if (check0 === undefined) {
+ t.warn('Render results with sampler.maxAnisotropy being 1 and 16 should be different.');
+ }
+ const check1 = checkElementsEqual(results[1].data, results[2].data);
+ if (check1 !== undefined) {
+ t.expect(
+ false,
+ 'Render results with sampler.maxAnisotropy being 16 and 1024 should be the same.'
+ );
+ }
+
+ for (const result of results) {
+ result.cleanup();
+ }
+ });
+
+g.test('anisotropic_filter_mipmap_color')
+ .desc(
+ `Anisotropic filter rendering tests that draws a slanted plane and samples from a texture
+ containing mipmaps of different colors. Given the same fragment with dFdx and dFdy for uv being different,
+ sampler with bigger maxAnisotropy value tends to bigger mip levels to provide better details.
+ We can then look at the color of the fragment to know which mip level is being sampled from and to see
+ if it fits expectations.
+ A similar webgl demo is at https://jsfiddle.net/t8k7c95o/5/`
+ )
+ .paramsSimple([
+ {
+ maxAnisotropy: 1,
+ _results: [
+ { coord: { x: xMiddle, y: 2 }, expected: colors[2] },
+ { coord: { x: xMiddle, y: 6 }, expected: [colors[0], colors[1]] },
+ ],
+
+ _generateWarningOnly: false,
+ },
+ {
+ maxAnisotropy: 4,
+ _results: [
+ { coord: { x: xMiddle, y: 2 }, expected: [colors[0], colors[1]] },
+ { coord: { x: xMiddle, y: 6 }, expected: colors[0] },
+ ],
+
+ _generateWarningOnly: true,
+ },
+ ])
+ .fn(async t => {
+ const texture = t.createTexture2DWithMipmaps(colors);
+
+ const textureView = texture.createView();
+
+ const sampler = t.device.createSampler({
+ magFilter: 'linear',
+ minFilter: 'linear',
+ mipmapFilter: 'linear',
+ maxAnisotropy: t.params.maxAnisotropy,
+ });
+
+ const colorAttachment = t.drawSlantedPlane(textureView, sampler);
+
+ for (const entry of t.params._results) {
+ if (entry.expected instanceof Uint8Array) {
+ // equal exactly one color
+ t.expectSinglePixelIn2DTexture(colorAttachment, kColorAttachmentFormat, entry.coord, {
+ exp: entry.expected,
+ generateWarningOnly: t.params._generateWarningOnly,
+ });
+ } else {
+ // a lerp between two colors
+ t.expectSinglePixelBetweenTwoValuesIn2DTexture(
+ colorAttachment,
+ kColorAttachmentFormat,
+ entry.coord,
+ {
+ exp: entry.expected,
+ generateWarningOnly: t.params._generateWarningOnly,
+ }
+ );
+ }
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/filter_mode.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/filter_mode.spec.js
new file mode 100644
index 0000000000..e67e308f18
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/filter_mode.spec.js
@@ -0,0 +1,15 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests the behavior of different filtering modes in minFilter/magFilter/mipmapFilter.
+
+TODO:
+- Test exact sampling results with small tolerance. Tests should differentiate between different
+ values for all three filter modes to make sure none are missed or incorrect in implementations.
+- (Likely unnecessary with the above.) Test exactly the expected number of samples are used.
+ Test this by setting up a rendering and asserting how many different shades result.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/lod_clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/lod_clamp.spec.js
new file mode 100644
index 0000000000..b05896a34d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/sampling/lod_clamp.spec.js
@@ -0,0 +1,13 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests the behavior of LOD clamping (lodMinClamp, lodMaxClamp).
+
+TODO:
+- Write a test that can test the exact clamping behavior
+- Test a bunch of values, including very large/small ones.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js
new file mode 100644
index 0000000000..52e2fb5870
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/shader_module/compilation_info.spec.js
@@ -0,0 +1,198 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+ShaderModule CompilationInfo tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const kValidShaderSources = [
+ {
+ valid: true,
+ name: 'ascii',
+ _code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ },
+ {
+ valid: true,
+ name: 'unicode',
+ _code: `
+ // 頂点シェーダー 👩‍💻
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ },
+];
+
+const kInvalidShaderSources = [
+ {
+ valid: false,
+ name: 'ascii',
+ _errorLine: 4,
+ _code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ // Expected Error: unknown function 'unknown'
+ return unknown(0.0, 0.0, 0.0, 1.0);
+ }`,
+ },
+ {
+ valid: false,
+ name: 'unicode',
+ _errorLine: 5,
+ _code: `
+ // 頂点シェーダー 👩‍💻
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ // Expected Error: unknown function 'unknown'
+ return unknown(0.0, 0.0, 0.0, 1.0);
+ }`,
+ },
+ {
+ valid: false,
+ name: 'carriage-return',
+ _errorLine: 5,
+ _code:
+ `
+ @vertex fn main() -> @builtin(position) vec4<f32> {` +
+ '\r\n' +
+ `
+ // Expected Error: unknown function 'unknown'
+ return unknown(0.0, 0.0, 0.0, 1.0);
+ }`,
+ },
+];
+
+const kAllShaderSources = [...kValidShaderSources, ...kInvalidShaderSources];
+
+g.test('compilationInfo_returns')
+ .desc(
+ `
+ Test that compilationInfo() can be called on any ShaderModule.
+ - Test for both valid and invalid shader modules.
+ - Test for shader modules containing only ASCII and those containing unicode characters.
+ - Test that the compilation info for valid shader modules contains no errors.
+ - Test that the compilation info for invalid shader modules contains at least one error.`
+ )
+ .paramsSimple(kAllShaderSources)
+ .fn(async t => {
+ const { _code, valid } = t.params;
+
+ const shaderModule = t.expectGPUError(
+ 'validation',
+ () => t.device.createShaderModule({ code: _code }),
+ !valid
+ );
+
+ const info = await shaderModule.compilationInfo();
+
+ t.expect(
+ info instanceof GPUCompilationInfo,
+ 'Expected a GPUCompilationInfo object to be returned'
+ );
+
+ // Expect that we get zero error messages from a valid shader.
+ // Message types other than errors are OK.
+ let errorCount = 0;
+ for (const message of info.messages) {
+ if (message.type === 'error') {
+ errorCount++;
+ }
+ }
+ if (valid) {
+ t.expect(errorCount === 0, "Expected zero GPUCompilationMessages of type 'error'");
+ } else {
+ t.expect(errorCount > 0, "Expected at least one GPUCompilationMessages of type 'error'");
+ }
+ });
+
+g.test('line_number_and_position')
+ .desc(
+ `
+ Test that line numbers reported by compilationInfo either point at an appropriate line and
+ position or at 0:0, indicating an unknown position.
+ - Test for invalid shader modules containing containing at least one error.
+ - Test for shader modules containing only ASCII and those containing unicode characters.`
+ )
+ .paramsSimple(kInvalidShaderSources)
+ .fn(async t => {
+ const { _code, _errorLine } = t.params;
+
+ const shaderModule = t.expectGPUError('validation', () =>
+ t.device.createShaderModule({ code: _code })
+ );
+
+ const info = await shaderModule.compilationInfo();
+
+ let foundAppropriateError = false;
+ for (const message of info.messages) {
+ if (message.type === 'error') {
+ // Some backends may not be able to indicate a precise location for the error. In those
+ // cases a line and position of 0 should be reported.
+ // If a line is reported, it should point at the correct line (1-based).
+ t.expect(
+ (message.lineNum === 0) === (message.linePos === 0),
+ "GPUCompilationMessages that don't report a line number should not report a line position."
+ );
+
+ if (message.lineNum === 0 || message.lineNum === _errorLine) {
+ foundAppropriateError = true;
+
+ // Various backends may choose to report the error at different positions within the line,
+ // so it's difficult to meaningfully validate them.
+ break;
+ }
+ }
+ }
+ t.expect(
+ foundAppropriateError,
+ 'Expected to find an error which corresponded with the erroneous line'
+ );
+ });
+
+g.test('offset_and_length')
+ .desc(
+ `Test that message offsets and lengths are valid and align with any reported lineNum and linePos.
+ - Test for valid and invalid shader modules.
+ - Test for shader modules containing only ASCII and those containing unicode characters.`
+ )
+ .paramsSimple(kAllShaderSources)
+ .fn(async t => {
+ const { _code, valid } = t.params;
+
+ const shaderModule = t.expectGPUError(
+ 'validation',
+ () => t.device.createShaderModule({ code: _code }),
+ !valid
+ );
+
+ const info = await shaderModule.compilationInfo();
+
+ for (const message of info.messages) {
+ // Any offsets and lengths should reference valid spans of the shader code.
+ t.expect(message.offset <= _code.length, 'Message offset should be within the shader source');
+ t.expect(
+ message.offset + message.length <= _code.length,
+ 'Message offset and length should be within the shader source'
+ );
+
+ // If a valid line number and position are given, the offset should point the the same
+ // location in the shader source.
+ if (message.lineNum !== 0 && message.linePos !== 0) {
+ let lineOffset = 0;
+ for (let i = 0; i < message.lineNum - 1; ++i) {
+ lineOffset = _code.indexOf('\n', lineOffset);
+ assert(lineOffset !== -1);
+ lineOffset += 1;
+ }
+
+ t.expect(
+ message.offset === lineOffset + message.linePos - 1,
+ 'lineNum and linePos should point to the same location as offset'
+ );
+ }
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js
new file mode 100644
index 0000000000..56187aede0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/format_reinterpretation.spec.js
@@ -0,0 +1,363 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test texture views can reinterpret the format of the original texture.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kRenderableColorTextureFormats,
+ kRegularTextureFormats,
+ viewCompatible,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { TexelView } from '../../../util/texture/texel_view.js';
+import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const kColors = [
+ { R: 1.0, G: 0.0, B: 0.0, A: 0.8 },
+ { R: 0.0, G: 1.0, B: 0.0, A: 0.7 },
+ { R: 0.0, G: 0.0, B: 0.0, A: 0.6 },
+ { R: 0.0, G: 0.0, B: 0.0, A: 0.5 },
+ { R: 1.0, G: 1.0, B: 1.0, A: 0.4 },
+ { R: 0.7, G: 0.0, B: 0.0, A: 0.3 },
+ { R: 0.0, G: 0.8, B: 0.0, A: 0.2 },
+ { R: 0.0, G: 0.0, B: 0.9, A: 0.1 },
+ { R: 0.1, G: 0.2, B: 0.0, A: 0.3 },
+ { R: 0.4, G: 0.3, B: 0.6, A: 0.8 },
+];
+
+const kTextureSize = 16;
+
+function makeInputTexelView(format) {
+ return TexelView.fromTexelsAsColors(
+ format,
+ coords => {
+ const pixelPos = coords.y * kTextureSize + coords.x;
+ return kColors[pixelPos % kColors.length];
+ },
+ { clampToFormatRange: true }
+ );
+}
+
+function makeBlitPipeline(device, format, multisample) {
+ return device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: device.createShaderModule({
+ code: `
+ @vertex fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>( 1.0, 1.0));
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module:
+ multisample.sample > 1
+ ? device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var src: texture_multisampled_2d<f32>;
+ @fragment fn main(@builtin(position) coord: vec4<f32>) -> @location(0) vec4<f32> {
+ var result : vec4<f32>;
+ for (var i = 0; i < ${multisample.sample}; i = i + 1) {
+ result = result + textureLoad(src, vec2<i32>(coord.xy), i);
+ }
+ return result * ${1 / multisample.sample};
+ }`,
+ })
+ : device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var src: texture_2d<f32>;
+ @fragment fn main(@builtin(position) coord: vec4<f32>) -> @location(0) vec4<f32> {
+ return textureLoad(src, vec2<i32>(coord.xy), 0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ multisample: {
+ count: multisample.render,
+ },
+ });
+}
+
+g.test('texture_binding')
+ .desc(`Test that a regular texture allocated as 'format' is correctly sampled as 'viewFormat'.`)
+ .params(u =>
+ u //
+ .combine('format', kRegularTextureFormats)
+ .combine('viewFormat', kRegularTextureFormats)
+ .filter(
+ ({ format, viewFormat }) => format !== viewFormat && viewCompatible(format, viewFormat)
+ )
+ )
+ .fn(async t => {
+ const { format, viewFormat } = t.params;
+
+ // Make an input texel view.
+ const inputTexelView = makeInputTexelView(format);
+
+ // Create the initial texture with the contents if the input texel view.
+ const texture = t.makeTextureWithContents(inputTexelView, {
+ size: [kTextureSize, kTextureSize],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [viewFormat],
+ });
+
+ // Reinterpret the texture as the view format.
+ // Make a texel view of the format that also reinterprets the data.
+ const reinterpretedView = texture.createView({ format: viewFormat });
+ const reinterpretedTexelView = TexelView.fromTexelsAsBytes(viewFormat, inputTexelView.bytes);
+
+ // Create a pipeline to write data out to rgba8unorm.
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var src: texture_2d<f32>;
+ @group(0) @binding(1) var dst: texture_storage_2d<rgba8unorm, write>;
+ @compute @workgroup_size(1, 1) fn main(
+ @builtin(global_invocation_id) global_id: vec3<u32>,
+ ) {
+ var coord = vec2<i32>(global_id.xy);
+ textureStore(dst, coord, textureLoad(src, coord, 0));
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ // Create an rgba8unorm output texture.
+ const outputTexture = t.trackForCleanup(
+ t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [kTextureSize, kTextureSize],
+ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC,
+ })
+ );
+
+ // Execute a compute pass to load data from the reinterpreted view and
+ // write out to the rgba8unorm texture.
+ const commandEncoder = t.device.createCommandEncoder();
+ const pass = commandEncoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(
+ 0,
+ t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: reinterpretedView,
+ },
+ {
+ binding: 1,
+ resource: outputTexture.createView(),
+ },
+ ],
+ })
+ );
+
+ pass.dispatchWorkgroups(kTextureSize, kTextureSize);
+ pass.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: outputTexture },
+ [kTextureSize, kTextureSize],
+ {
+ expTexelView: TexelView.fromTexelsAsColors('rgba8unorm', reinterpretedTexelView.color, {
+ clampToFormatRange: true,
+ }),
+ },
+ { maxDiffULPsForNormFormat: 1 }
+ );
+
+ t.expectOK(result);
+ });
+
+g.test('render_and_resolve_attachment')
+ .desc(
+ `Test that a color render attachment allocated as 'format' is correctly rendered to as 'viewFormat',
+and resolved to an attachment allocated as 'format' viewed as 'viewFormat'.
+
+Other combinations aren't possible because the render and resolve targets must both match
+in view format and match in base format.`
+ )
+ .params(u =>
+ u //
+ .combine('format', kRenderableColorTextureFormats)
+ .combine('viewFormat', kRenderableColorTextureFormats)
+ .filter(
+ ({ format, viewFormat }) => format !== viewFormat && viewCompatible(format, viewFormat)
+ )
+ .combine('sampleCount', [1, 4])
+ )
+ .fn(async t => {
+ const { format, viewFormat, sampleCount } = t.params;
+
+ // Make an input texel view.
+ const inputTexelView = makeInputTexelView(format);
+
+ // Create the renderTexture as |format|.
+ const renderTexture = t.trackForCleanup(
+ t.device.createTexture({
+ format,
+ size: [kTextureSize, kTextureSize],
+ usage:
+ GPUTextureUsage.RENDER_ATTACHMENT |
+ (sampleCount > 1 ? GPUTextureUsage.TEXTURE_BINDING : GPUTextureUsage.COPY_SRC),
+ viewFormats: [viewFormat],
+ sampleCount,
+ })
+ );
+
+ const resolveTexture =
+ sampleCount === 1
+ ? undefined
+ : t.trackForCleanup(
+ t.device.createTexture({
+ format,
+ size: [kTextureSize, kTextureSize],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ viewFormats: [viewFormat],
+ })
+ );
+
+ // Create the sample source with the contents of the input texel view.
+ // We will sample this texture into |renderTexture|. It uses the same format to keep the same
+ // number of bits of precision.
+ const sampleSource = t.makeTextureWithContents(inputTexelView, {
+ size: [kTextureSize, kTextureSize],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ // Reinterpret the renderTexture as |viewFormat|.
+ const reinterpretedRenderView = renderTexture.createView({ format: viewFormat });
+ const reinterpretedResolveView =
+ resolveTexture && resolveTexture.createView({ format: viewFormat });
+
+ // Create a pipeline to blit a src texture to the render attachment.
+ const pipeline = makeBlitPipeline(t.device, viewFormat, {
+ sample: 1,
+ render: sampleCount,
+ });
+
+ // Execute a render pass to sample |sampleSource| into |texture| viewed as |viewFormat|.
+ const commandEncoder = t.device.createCommandEncoder();
+ const pass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: reinterpretedRenderView,
+ resolveTarget: reinterpretedResolveView,
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(
+ 0,
+ t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: sampleSource.createView(),
+ },
+ ],
+ })
+ );
+
+ pass.draw(6);
+ pass.end();
+
+ // If the render target is multisampled, we'll manually resolve it to check
+ // the contents.
+ const singleSampleRenderTexture = resolveTexture
+ ? t.trackForCleanup(
+ t.device.createTexture({
+ format,
+ size: [kTextureSize, kTextureSize],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ )
+ : renderTexture;
+
+ if (resolveTexture) {
+ // Create a pipeline to blit the multisampled render texture to a non-multisample texture.
+ // We are basically performing a manual resolve step to the same format as the original
+ // render texture to check its contents.
+ const pipeline = makeBlitPipeline(t.device, format, { sample: sampleCount, render: 1 });
+ const pass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: singleSampleRenderTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(
+ 0,
+ t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: renderTexture.createView(),
+ },
+ ],
+ })
+ );
+
+ pass.draw(6);
+ pass.end();
+ }
+
+ // Submit the commands.
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ // Check the rendered contents.
+ const renderViewTexels = TexelView.fromTexelsAsColors(viewFormat, inputTexelView.color, {
+ clampToFormatRange: true,
+ });
+ t.expectOK(
+ await textureContentIsOKByT2B(
+ t,
+ { texture: singleSampleRenderTexture },
+ [kTextureSize, kTextureSize],
+ { expTexelView: renderViewTexels },
+ { maxDiffULPsForNormFormat: 2 }
+ )
+ );
+
+ // Check the resolved contents.
+ if (resolveTexture) {
+ const resolveView = TexelView.fromTexelsAsColors(viewFormat, renderViewTexels.color, {
+ clampToFormatRange: true,
+ });
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture: resolveTexture },
+ [kTextureSize, kTextureSize],
+ { expTexelView: resolveView },
+ { maxDiffULPsForNormFormat: 2 }
+ );
+
+ t.expectOK(result);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/read.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/read.spec.js
new file mode 100644
index 0000000000..96884efec5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/read.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test the result of reading textures through texture views with various options.
+
+All x= every possible view read method: {
+ - {unfiltered, filtered (if valid), comparison (if valid)} sampling
+ - storage read {vertex, fragment, compute}
+ - no-op render pass that loads and then stores
+ - depth comparison
+ - stencil comparison
+}
+
+Format reinterpretation is not tested here. It is in format_reinterpretation.spec.ts.
+
+TODO: Write helper for this if not already available (see resource_init, buffer_sync_test for related code).
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('format')
+ .desc(
+ `Views of every allowed format.
+
+- x= every texture format
+- x= sampleCount {1, 4} if valid
+- x= every possible view read method (see above)
+`
+ )
+ .unimplemented();
+
+g.test('dimension')
+ .desc(
+ `Views of every allowed dimension.
+
+- x= a representative subset of formats
+- x= {every texture dimension} x {every valid view dimension}
+ (per gpuweb#79 no dimension-count reinterpretations, like 2d-array <-> 3d, are possible)
+- x= sampleCount {1, 4} if valid
+- x= every possible view read method (see above)
+`
+ )
+ .unimplemented();
+
+g.test('aspect')
+ .desc(
+ `Views of every allowed aspect of depth/stencil textures.
+
+- x= every depth/stencil format
+- x= {"all", "stencil-only", "depth-only"} where valid for the format
+- x= sampleCount {1, 4} if valid
+- x= every possible view read method (see above)
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js
new file mode 100644
index 0000000000..3a47c0360e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/texture_view/write.spec.js
@@ -0,0 +1,55 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test the result of writing textures through texture views with various options.
+
+All x= every possible view write method: {
+ - storage write {fragment, compute}
+ - render pass store
+ - render pass resolve
+}
+
+Format reinterpretation is not tested here. It is in format_reinterpretation.spec.ts.
+
+TODO: Write helper for this if not already available (see resource_init, buffer_sync_test for related code).
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('format')
+ .desc(
+ `Views of every allowed format.
+
+- x= every texture format
+- x= sampleCount {1, 4} if valid
+- x= every possible view write method (see above)
+`
+ )
+ .unimplemented();
+
+g.test('dimension')
+ .desc(
+ `Views of every allowed dimension.
+
+- x= a representative subset of formats
+- x= {every texture dimension} x {every valid view dimension}
+ (per gpuweb#79 no dimension-count reinterpretations, like 2d-array <-> 3d, are possible)
+- x= sampleCount {1, 4} if valid
+- x= every possible view write method (see above)
+`
+ )
+ .unimplemented();
+
+g.test('aspect')
+ .desc(
+ `Views of every allowed aspect of depth/stencil textures.
+
+- x= every depth/stencil format
+- x= {"all", "stencil-only", "depth-only"} where valid for the format
+- x= sampleCount {1, 4} if valid
+- x= every possible view write method (see above)
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/uncapturederror.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/uncapturederror.spec.js
new file mode 100644
index 0000000000..acd39ae972
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/uncapturederror.spec.js
@@ -0,0 +1,35 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for GPUDevice.onuncapturederror.
+`;
+import { Fixture } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+export const g = makeTestGroup(Fixture);
+
+g.test('constructor')
+ .desc(
+ `GPUUncapturedErrorEvent constructor options (also tests constructing GPUOutOfMemoryError/GPUValidationError)`
+ )
+ .unimplemented();
+
+g.test('iff_uncaptured')
+ .desc(
+ `{validation, out-of-memory} error should fire uncapturederror iff not captured by a scope.`
+ )
+ .unimplemented();
+
+g.test('only_original_device_is_event_target')
+ .desc(
+ `Original GPUDevice objects are EventTargets and have onuncapturederror, but
+deserialized GPUDevices do not.`
+ )
+ .unimplemented();
+
+g.test('uncapturederror_from_non_originating_thread')
+ .desc(
+ `Uncaptured errors on any thread should always propagate to the original GPUDevice object
+(since deserialized ones don't have EventTarget/onuncapturederror).`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/correctness.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/correctness.spec.js
new file mode 100644
index 0000000000..0d6ffc853e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/correctness.spec.js
@@ -0,0 +1,1067 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO: Test more corner case values for Float16 / Float32 (INF, NaN, +-0, ...) and reduce the
+float tolerance.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, memcpy, unreachable } from '../../../../common/util/util.js';
+import {
+ kMaxVertexAttributes,
+ kMaxVertexBufferArrayStride,
+ kMaxVertexBuffers,
+ kPerStageBindingLimits,
+ kVertexFormatInfo,
+ kVertexFormats,
+} from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { float32ToFloat16Bits, normalizedIntegerAsFloat } from '../../../util/conversion.js';
+import { align, clamp } from '../../../util/math.js';
+
+// These types mirror the structure of GPUVertexBufferLayout but allow defining the extra
+// dictionary members at the GPUVertexBufferLayout and GPUVertexAttribute level. The are used
+// like so:
+//
+// VertexState<{arrayStride: number}, {format: VertexFormat}>
+// VertexBuffer<{arrayStride: number}, {format: VertexFormat}>
+// VertexAttrib<{format: VertexFormat}>
+
+function mapBufferAttribs(buffer, f) {
+ const newAttributes = [];
+ for (const a of buffer.attributes) {
+ newAttributes.push({
+ shaderLocation: a.shaderLocation,
+ ...f(buffer, a),
+ });
+ }
+
+ return { ...buffer, attributes: newAttributes };
+}
+
+function mapStateAttribs(buffers, f) {
+ return buffers.map(b => mapBufferAttribs(b, f));
+}
+
+class VertexStateTest extends GPUTest {
+ // Generate for VS + FS (entrypoints vsMain / fsMain) that for each attribute will check that its
+ // value corresponds to what's expected (as provided by a uniform buffer per attribute) and then
+ // renders each vertex at position (vertexIndex, instanceindex) with either 1 (success) or
+ // a negative number corresponding to the check number (in case you need to debug a failure).
+ makeTestWGSL(
+ buffers,
+
+ vertexCount,
+ instanceCount
+ ) {
+ // In the base WebGPU spec maxVertexAttributes is larger than maxUniformBufferPerStage. We'll
+ // use a combination of uniform and storage buffers to cover all possible attributes. This
+ // happens to work because maxUniformBuffer + maxStorageBuffer = 12 + 8 = 20 which is larger
+ // than maxVertexAttributes = 16.
+ // However this might not work in the future for implementations that allow even more vertex
+ // attributes so there will need to be larger changes when that happens.
+ const maxUniformBuffers = kPerStageBindingLimits['uniformBuf'].max;
+ assert(maxUniformBuffers + kPerStageBindingLimits['storageBuf'].max >= kMaxVertexAttributes);
+
+ let vsInputs = '';
+ let vsChecks = '';
+ let vsBindings = '';
+
+ for (const b of buffers) {
+ for (const a of b.attributes) {
+ const format = kVertexFormatInfo[a.format];
+ const shaderComponentCount = a.shaderComponentCount ?? format.componentCount;
+ const i = a.shaderLocation;
+
+ // shaderType is either a scalar type like f32 or a vecN<scalarType>
+ let shaderType = a.shaderBaseType;
+ if (shaderComponentCount !== 1) {
+ shaderType = `vec${shaderComponentCount}<${shaderType}>`;
+ }
+
+ let maxCount = `${vertexCount}`;
+ let indexBuiltin = `input.vertexIndex`;
+ if (b.stepMode === 'instance') {
+ maxCount = `${instanceCount}`;
+ indexBuiltin = `input.instanceIndex`;
+ }
+
+ // Start using storage buffers when we run out of uniform buffers.
+ let storageType = 'uniform';
+ if (i >= maxUniformBuffers) {
+ storageType = 'storage, read';
+ }
+
+ vsInputs += ` @location(${i}) attrib${i} : ${shaderType},\n`;
+ vsBindings += `struct S${i} { data : array<vec4<${a.shaderBaseType}>, ${maxCount}> };\n`;
+ vsBindings += `@group(0) @binding(${i}) var<${storageType}> providedData${i} : S${i};\n`;
+
+ // Generate the all the checks for the attributes.
+ for (let component = 0; component < shaderComponentCount; component++) {
+ // Components are filled with (0, 0, 0, 1) if they aren't provided data from the pipeline.
+ if (component >= format.componentCount) {
+ const expected = component === 3 ? '1' : '0';
+ vsChecks += ` check(input.attrib${i}[${component}] == ${a.shaderBaseType}(${expected}));\n`;
+ continue;
+ }
+
+ // Check each component individually, with special handling of tolerance for floats.
+ const attribComponent =
+ shaderComponentCount === 1 ? `input.attrib${i}` : `input.attrib${i}[${component}]`;
+ const providedData = `providedData${i}.data[${indexBuiltin}][${component}]`;
+ if (format.type === 'uint' || format.type === 'sint') {
+ vsChecks += ` check(${attribComponent} == ${providedData});\n`;
+ } else {
+ vsChecks += ` check(floatsSimilar(${attribComponent}, ${providedData}, f32(${
+ a.floatTolerance ?? 0
+ })));\n`;
+ }
+ }
+ }
+ }
+
+ return `
+struct Inputs {
+${vsInputs}
+ @builtin(vertex_index) vertexIndex: u32,
+ @builtin(instance_index) instanceIndex: u32,
+};
+
+${vsBindings}
+
+var<private> vsResult : i32 = 1;
+var<private> checkIndex : i32 = 0;
+fn check(success : bool) {
+ if (!success) {
+ vsResult = -checkIndex;
+ }
+ checkIndex = checkIndex + 1;
+}
+
+fn floatsSimilar(a : f32, b : f32, tolerance : f32) -> bool {
+ // TODO do we check for + and - 0?
+ return abs(a - b) < tolerance;
+}
+
+fn doTest(input : Inputs) {
+${vsChecks}
+}
+
+struct VSOutputs {
+ @location(0) @interpolate(flat) result : i32,
+ @builtin(position) position : vec4<f32>,
+};
+
+@vertex fn vsMain(input : Inputs) -> VSOutputs {
+ doTest(input);
+
+ // Place that point at pixel (vertexIndex, instanceIndex) in a framebuffer of size
+ // (vertexCount , instanceCount).
+ var output : VSOutputs;
+ output.position = vec4<f32>(
+ ((f32(input.vertexIndex) + 0.5) / ${vertexCount}.0 * 2.0) - 1.0,
+ ((f32(input.instanceIndex) + 0.5) / ${instanceCount}.0 * 2.0) - 1.0,
+ 0.0, 1.0
+ );
+ output.result = vsResult;
+ return output;
+}
+
+@fragment fn fsMain(@location(0) @interpolate(flat) result : i32)
+ -> @location(0) i32 {
+ return result;
+}
+ `;
+ }
+
+ makeTestPipeline(
+ buffers,
+
+ vertexCount,
+ instanceCount
+ ) {
+ const module = this.device.createShaderModule({
+ code: this.makeTestWGSL(buffers, vertexCount, instanceCount),
+ });
+
+ const bufferLayouts = [];
+ for (const b of buffers) {
+ bufferLayouts[b.slot] = b;
+ }
+
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'vsMain',
+ buffers: bufferLayouts,
+ },
+ primitive: {
+ topology: 'point-list',
+ },
+ fragment: {
+ module,
+ entryPoint: 'fsMain',
+ targets: [
+ {
+ format: 'r32sint',
+ },
+ ],
+ },
+ });
+ }
+
+ // Runs the render pass drawing points in a vertexCount*instanceCount rectangle, then check each
+ // of produced a value of 1 which means that the tests in the shader passed.
+ submitRenderPass(pipeline, buffers, expectedData, vertexCount, instanceCount) {
+ const testTexture = this.device.createTexture({
+ format: 'r32sint',
+ size: [vertexCount, instanceCount],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: testTexture.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, expectedData);
+ for (const buffer of buffers) {
+ pass.setVertexBuffer(buffer.slot, buffer.buffer, buffer.vbOffset ?? 0);
+ }
+ pass.draw(vertexCount, instanceCount);
+ pass.end();
+
+ this.device.queue.submit([encoder.finish()]);
+
+ this.expectSingleColor(testTexture, 'r32sint', {
+ size: [vertexCount, instanceCount, 1],
+ exp: { R: 1 },
+ });
+ }
+
+ // Generate TestData for the format with interesting test values.
+ // MAINTENANCE_TODO cache the result on the fixture?
+ // Note that the test data always starts with an interesting value, so that using the first
+ // test value in a test is still meaningful.
+ generateTestData(format) {
+ const formatInfo = kVertexFormatInfo[format];
+ const bitSize = formatInfo.bytesPerComponent * 8;
+
+ switch (formatInfo.type) {
+ case 'float': {
+ const data = [42.42, 0.0, 1.0, -1.0, 1000, -18.7, 25.17];
+ const expectedData = new Float32Array(data).buffer;
+ const vertexData =
+ bitSize === 32
+ ? expectedData
+ : bitSize === 16
+ ? new Uint16Array(data.map(float32ToFloat16Bits)).buffer
+ : unreachable();
+
+ return {
+ shaderBaseType: 'f32',
+ testComponentCount: data.length,
+ expectedData,
+ vertexData,
+ floatTolerance: 0.05,
+ };
+ }
+
+ case 'sint': {
+ const data = [
+ 42,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ -1,
+ -2,
+ -3,
+ -4,
+ -5,
+ Math.pow(2, bitSize - 2),
+ Math.pow(2, bitSize - 1) - 1, // max value
+ -Math.pow(2, bitSize - 2),
+ -Math.pow(2, bitSize - 1), // min value
+ ];
+ const expectedData = new Int32Array(data).buffer;
+ const vertexData =
+ bitSize === 32
+ ? expectedData
+ : bitSize === 16
+ ? new Int16Array(data).buffer
+ : new Int8Array(data).buffer;
+
+ return {
+ shaderBaseType: 'i32',
+ testComponentCount: data.length,
+ expectedData,
+ vertexData,
+ };
+ }
+
+ case 'uint': {
+ const data = [
+ 42,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ Math.pow(2, bitSize - 1),
+ Math.pow(2, bitSize) - 1, // max value
+ ];
+ const expectedData = new Uint32Array(data).buffer;
+ const vertexData =
+ bitSize === 32
+ ? expectedData
+ : bitSize === 16
+ ? new Uint16Array(data).buffer
+ : new Uint8Array(data).buffer;
+
+ return {
+ shaderBaseType: 'u32',
+ testComponentCount: data.length,
+ expectedData,
+ vertexData,
+ };
+ }
+
+ case 'snorm': {
+ const data = [
+ 42,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ -1,
+ -2,
+ -3,
+ -4,
+ -5,
+ Math.pow(2, bitSize - 2),
+ Math.pow(2, bitSize - 1) - 1, // max value
+ -Math.pow(2, bitSize - 2),
+ -Math.pow(2, bitSize - 1), // min value
+ ];
+ const vertexData =
+ bitSize === 16
+ ? new Int16Array(data).buffer
+ : bitSize === 8
+ ? new Int8Array(data).buffer
+ : unreachable();
+
+ return {
+ shaderBaseType: 'f32',
+ testComponentCount: data.length,
+ expectedData: new Float32Array(data.map(v => normalizedIntegerAsFloat(v, bitSize, true)))
+ .buffer,
+ vertexData,
+ floatTolerance: 0.1 * normalizedIntegerAsFloat(1, bitSize, true),
+ };
+ }
+
+ case 'unorm': {
+ const data = [
+ 42,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ Math.pow(2, bitSize - 1),
+ Math.pow(2, bitSize) - 1, // max value
+ ];
+ const vertexData =
+ bitSize === 16
+ ? new Uint16Array(data).buffer
+ : bitSize === 8
+ ? new Uint8Array(data).buffer
+ : unreachable();
+
+ return {
+ shaderBaseType: 'f32',
+ testComponentCount: data.length,
+ expectedData: new Float32Array(data.map(v => normalizedIntegerAsFloat(v, bitSize, false)))
+ .buffer,
+ vertexData,
+ floatTolerance: 0.1 * normalizedIntegerAsFloat(1, bitSize, false),
+ };
+ }
+ }
+ }
+
+ // The TestData generated for a format might not contain enough data for all the vertices we are
+ // going to draw, so we expand them by adding additional copies of the vertexData as needed.
+ // expectedData is a bit different because it also needs to be unpacked to have `componentCount`
+ // components every 4 components (because the shader uses vec4 for the expected data).
+ expandTestData(data, maxCount, componentCount) {
+ const vertexComponentSize = data.vertexData.byteLength / data.testComponentCount;
+ const expectedComponentSize = data.expectedData.byteLength / data.testComponentCount;
+
+ const expandedVertexData = new Uint8Array(maxCount * componentCount * vertexComponentSize);
+ const expandedExpectedData = new Uint8Array(4 * maxCount * expectedComponentSize);
+
+ for (let index = 0; index < maxCount; index++) {
+ for (let component = 0; component < componentCount; component++) {
+ // If only we had some builtin JS memcpy function between ArrayBuffers...
+ const targetVertexOffset = (index * componentCount + component) * vertexComponentSize;
+ const sourceVertexOffset = targetVertexOffset % data.vertexData.byteLength;
+ memcpy(
+ { src: data.vertexData, start: sourceVertexOffset, length: vertexComponentSize },
+ { dst: expandedVertexData, start: targetVertexOffset }
+ );
+
+ const targetExpectedOffset = (index * 4 + component) * expectedComponentSize;
+ const sourceExpectedOffset =
+ ((index * componentCount + component) * expectedComponentSize) %
+ data.expectedData.byteLength;
+ memcpy(
+ { src: data.expectedData, start: sourceExpectedOffset, length: expectedComponentSize },
+ { dst: expandedExpectedData, start: targetExpectedOffset }
+ );
+ }
+ }
+
+ return {
+ shaderBaseType: data.shaderBaseType,
+ testComponentCount: maxCount * componentCount,
+ floatTolerance: data.floatTolerance,
+ expectedData: expandedExpectedData.buffer,
+ vertexData: expandedVertexData.buffer,
+ };
+ }
+
+ // Copies `size` bytes from `source` to `target` starting at `offset` each `targetStride`.
+ // (the data in `source` is assumed packed)
+ interleaveVertexDataInto(target, src, { targetStride, offset, size }) {
+ const dst = new Uint8Array(target);
+ for (
+ let srcStart = 0, dstStart = offset;
+ srcStart < src.byteLength;
+ srcStart += size, dstStart += targetStride
+ ) {
+ memcpy({ src, start: srcStart, length: size }, { dst, start: dstStart });
+ }
+ }
+
+ createTestAndPipelineData(state, vertexCount, instanceCount) {
+ // Gather the test data and some additional test state for attribs.
+ return mapStateAttribs(state, (buffer, attrib) => {
+ const maxCount = buffer.stepMode === 'instance' ? instanceCount : vertexCount;
+ const formatInfo = kVertexFormatInfo[attrib.format];
+
+ let testData = this.generateTestData(attrib.format);
+ testData = this.expandTestData(testData, maxCount, formatInfo.componentCount);
+
+ return {
+ ...testData,
+ ...attrib,
+ };
+ });
+ }
+
+ createExpectedBG(state, pipeline) {
+ // Create the bindgroups from that test data
+ const bgEntries = [];
+
+ for (const buffer of state) {
+ for (const attrib of buffer.attributes) {
+ const expectedDataBuffer = this.makeBufferWithContents(
+ new Uint8Array(attrib.expectedData),
+ GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE
+ );
+
+ bgEntries.push({
+ binding: attrib.shaderLocation,
+ resource: { buffer: expectedDataBuffer },
+ });
+ }
+ }
+
+ return this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: bgEntries,
+ });
+ }
+
+ createVertexBuffers(state, vertexCount, instanceCount) {
+ // Create the vertex buffers
+ const vertexBuffers = [];
+
+ for (const buffer of state) {
+ const maxCount = buffer.stepMode === 'instance' ? instanceCount : vertexCount;
+
+ // Fill the vertex data with garbage so that we don't get `0` (which could be a test value)
+ // if the vertex shader loads the vertex data incorrectly.
+ const vertexData = new ArrayBuffer(
+ align(buffer.arrayStride * maxCount + (buffer.vbOffset ?? 0), 4)
+ );
+
+ new Uint8Array(vertexData).fill(0xc4);
+
+ for (const attrib of buffer.attributes) {
+ const formatInfo = kVertexFormatInfo[attrib.format];
+ this.interleaveVertexDataInto(vertexData, attrib.vertexData, {
+ targetStride: buffer.arrayStride,
+ offset: (buffer.vbOffset ?? 0) + attrib.offset,
+ size: formatInfo.componentCount * formatInfo.bytesPerComponent,
+ });
+ }
+
+ vertexBuffers.push({
+ slot: buffer.slot,
+ buffer: this.makeBufferWithContents(new Uint8Array(vertexData), GPUBufferUsage.VERTEX),
+ vbOffset: buffer.vbOffset,
+ attributes: [],
+ });
+ }
+
+ return vertexBuffers;
+ }
+
+ runTest(
+ buffers,
+ // Default to using 20 vertices and 20 instances so that we cover each of the test data at least
+ // once (at the time of writing the largest testData has 16 values).
+ vertexCount = 20,
+ instanceCount = 20
+ ) {
+ const testData = this.createTestAndPipelineData(buffers, vertexCount, instanceCount);
+ const pipeline = this.makeTestPipeline(testData, vertexCount, instanceCount);
+ const expectedDataBG = this.createExpectedBG(testData, pipeline);
+ const vertexBuffers = this.createVertexBuffers(testData, vertexCount, instanceCount);
+ this.submitRenderPass(pipeline, vertexBuffers, expectedDataBG, vertexCount, instanceCount);
+ }
+}
+
+export const g = makeTestGroup(VertexStateTest);
+
+g.test('vertex_format_to_shader_format_conversion')
+ .desc(
+ `Test that the raw data passed in vertex buffers is correctly converted to the input type in the shader. Test for:
+ - all formats
+ - 1 to 4 components in the shader's input type (unused components are filled with 0 and except the 4th with 1)
+ - various locations
+ - various slots`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .combine('shaderComponentCount', [1, 2, 3, 4])
+ .beginSubcases()
+ .combine('slot', [0, 1, kMaxVertexBuffers - 1])
+ .combine('shaderLocation', [0, 1, kMaxVertexAttributes - 1])
+ )
+ .fn(t => {
+ const { format, shaderComponentCount, slot, shaderLocation } = t.params;
+ t.runTest([
+ {
+ slot,
+ arrayStride: 16,
+ stepMode: 'vertex',
+ attributes: [
+ {
+ shaderLocation,
+ format,
+ offset: 0,
+ shaderComponentCount,
+ },
+ ],
+ },
+ ]);
+ });
+
+g.test('setVertexBuffer_offset_and_attribute_offset')
+ .desc(
+ `Test that the vertex buffer offset and attribute offset in the vertex state are applied correctly. Test for:
+ - all formats
+ - various setVertexBuffer offsets
+ - various attribute offsets in a fixed arrayStride`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('vbOffset', [0, 4, 400, 1004])
+ .combine('arrayStride', [128])
+ .expand('offset', p => {
+ const formatInfo = kVertexFormatInfo[p.format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ return new Set([
+ 0,
+ 4,
+ 8,
+ formatSize,
+ formatSize * 2,
+ p.arrayStride / 2,
+ p.arrayStride - formatSize - 4,
+ p.arrayStride - formatSize - 8,
+ p.arrayStride - formatSize - formatSize,
+ p.arrayStride - formatSize - formatSize * 2,
+ p.arrayStride - formatSize,
+ ]);
+ })
+ )
+ .fn(t => {
+ const { format, vbOffset, arrayStride, offset } = t.params;
+ t.runTest([
+ {
+ slot: 0,
+ arrayStride,
+ stepMode: 'vertex',
+ vbOffset,
+ attributes: [
+ {
+ shaderLocation: 0,
+ format,
+ offset,
+ },
+ ],
+ },
+ ]);
+ });
+
+g.test('non_zero_array_stride_and_attribute_offset')
+ .desc(
+ `Test that the array stride and attribute offset in the vertex state are applied correctly. Test for:
+ - all formats
+ - various array strides
+ - various attribute offsets in a fixed arrayStride`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .expand('arrayStride', p => {
+ const formatInfo = kVertexFormatInfo[p.format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+
+ return [align(formatSize, 4), align(formatSize, 4) + 4, kMaxVertexBufferArrayStride];
+ })
+ .expand('offset', p => {
+ const formatInfo = kVertexFormatInfo[p.format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ return new Set(
+ [
+ 0,
+ formatSize,
+ 4,
+ p.arrayStride / 2,
+ p.arrayStride - formatSize * 2,
+ p.arrayStride - formatSize - 4,
+ p.arrayStride - formatSize,
+ ].map(offset => clamp(offset, { min: 0, max: p.arrayStride - formatSize }))
+ );
+ })
+ )
+ .fn(t => {
+ const { format, arrayStride, offset } = t.params;
+ t.runTest([
+ {
+ slot: 0,
+ arrayStride,
+ stepMode: 'vertex',
+ attributes: [
+ {
+ shaderLocation: 0,
+ format,
+ offset,
+ },
+ ],
+ },
+ ]);
+ });
+
+g.test('buffers_with_varying_step_mode')
+ .desc(
+ `Test buffers with varying step modes in the same vertex state.
+ - Various combination of step modes`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('stepModes', [
+ ['instance'],
+ ['vertex', 'vertex', 'instance'],
+ ['instance', 'vertex', 'instance'],
+ ['vertex', 'instance', 'vertex', 'vertex'],
+ ])
+ )
+ .fn(t => {
+ const { stepModes } = t.params;
+ const state = stepModes.map((stepMode, i) => ({
+ slot: i,
+ arrayStride: 4,
+ stepMode,
+ attributes: [
+ {
+ shaderLocation: i,
+ format: 'float32',
+ offset: 0,
+ },
+ ],
+ }));
+ t.runTest(state);
+ });
+
+g.test('vertex_buffer_used_multiple_times_overlapped')
+ .desc(
+ `Test using the same vertex buffer in for multiple "vertex buffers", with data from each buffer overlapping.
+ - For each vertex format.
+ - For various numbers of vertex buffers [2, 3, max]`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('vbCount', [2, 3, kMaxVertexBuffers])
+ .combine('additionalVBOffset', [0, 4, 120])
+ )
+ .fn(t => {
+ const { format, vbCount, additionalVBOffset } = t.params;
+ const kVertexCount = 20;
+ const kInstanceCount = 1;
+ const formatInfo = kVertexFormatInfo[format];
+ const formatByteSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ // We need to align so the offset for non-0 setVertexBuffer don't fail validation.
+ const alignedFormatByteSize = align(formatByteSize, 4);
+
+ // In this test we want to test using the same vertex buffer for multiple different attributes.
+ // For example if vbCount is 3, we will create a vertex buffer containing the following data:
+ // a0, a1, a2, a3, ..., a<baseDataVertexCount>
+ // We also create the expected data for the vertex fetching from that buffer so we can modify it
+ // below.
+ const baseDataVertexCount = kVertexCount + vbCount - 1;
+ const baseData = t.createTestAndPipelineData(
+ [
+ {
+ slot: 0,
+ arrayStride: alignedFormatByteSize,
+ stepMode: 'vertex',
+ vbOffset: additionalVBOffset,
+ attributes: [{ shaderLocation: 0, format, offset: 0 }],
+ },
+ ],
+
+ baseDataVertexCount,
+ kInstanceCount
+ );
+
+ const vertexBuffer = t.createVertexBuffers(baseData, baseDataVertexCount, kInstanceCount)[0]
+ .buffer;
+
+ // We are going to bind the vertex buffer multiple times, each time at a different offset that's
+ // a multiple of the data size. So what should be fetched by the vertex shader is:
+ // - attrib0: a0, a1, ..., a19
+ // - attrib1: a1, a2, ..., a20
+ // - attrib2: a2, a3, ..., a21
+ // etc.
+ // We re-create the test data by:
+ // 1) creating multiple "vertex buffers" that all point at the GPUBuffer above but at
+ // different offsets.
+ // 2) selecting what parts of the expectedData each attribute will see in the expectedData for
+ // the full vertex buffer.
+ const baseTestData = baseData[0].attributes[0];
+ assert(baseTestData.testComponentCount === formatInfo.componentCount * baseDataVertexCount);
+ const expectedDataBytesPerVertex = baseTestData.expectedData.byteLength / baseDataVertexCount;
+
+ const testData = [];
+ const vertexBuffers = [];
+ for (let i = 0; i < vbCount; i++) {
+ vertexBuffers.push({
+ buffer: vertexBuffer,
+ slot: i,
+ vbOffset: additionalVBOffset + i * alignedFormatByteSize,
+ attributes: [],
+ });
+
+ testData.push({
+ slot: i,
+ arrayStride: alignedFormatByteSize,
+ stepMode: 'vertex',
+ attributes: [
+ {
+ shaderLocation: i,
+ format,
+ offset: 0,
+
+ shaderBaseType: baseTestData.shaderBaseType,
+ floatTolerance: baseTestData.floatTolerance,
+ // Select vertices [i, i + kVertexCount]
+ testComponentCount: kVertexCount * formatInfo.componentCount,
+ expectedData: baseTestData.expectedData.slice(
+ expectedDataBytesPerVertex * i,
+ expectedDataBytesPerVertex * (kVertexCount + i)
+ ),
+
+ vertexData: new ArrayBuffer(0),
+ },
+ ],
+ });
+ }
+
+ // Run the test with the modified test data.
+ const pipeline = t.makeTestPipeline(testData, kVertexCount, kInstanceCount);
+ const expectedDataBG = t.createExpectedBG(testData, pipeline);
+ t.submitRenderPass(pipeline, vertexBuffers, expectedDataBG, kVertexCount, kInstanceCount);
+ });
+
+g.test('vertex_buffer_used_multiple_times_interleaved')
+ .desc(
+ `Test using the same vertex buffer in for multiple "vertex buffers", with data from each buffer interleaved.
+ - For each vertex format.
+ - For various numbers of vertex buffers [2, 3, max]`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('vbCount', [2, 3, kMaxVertexBuffers])
+ .combine('additionalVBOffset', [0, 4, 120])
+ )
+ .fn(t => {
+ const { format, vbCount, additionalVBOffset } = t.params;
+ const kVertexCount = 20;
+ const kInstanceCount = 1;
+ const formatInfo = kVertexFormatInfo[format];
+ const formatByteSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ // We need to align so the offset for non-0 setVertexBuffer don't fail validation.
+ const alignedFormatByteSize = align(formatByteSize, 4);
+
+ // Create data for a single vertex buffer with many attributes, that will be split between
+ // many vertex buffers set at different offsets.
+
+ // In this test we want to test using the same vertex buffer for multiple different attributes.
+ // For example if vbCount is 3, we will create a vertex buffer containing the following data:
+ // a0, a0, a0, a1, a1, a1, ...
+ // To do that we create a single vertex buffer with `vbCount` attributes that all have the same
+ // format.
+ const attribs = [];
+ for (let i = 0; i < vbCount; i++) {
+ attribs.push({ format, offset: i * alignedFormatByteSize, shaderLocation: i });
+ }
+ const baseData = t.createTestAndPipelineData(
+ [
+ {
+ slot: 0,
+ arrayStride: alignedFormatByteSize * vbCount,
+ stepMode: 'vertex',
+ vbOffset: additionalVBOffset,
+ attributes: attribs,
+ },
+ ],
+
+ // Request one vertex more than what we need so we have an extra full stride. Otherwise WebGPU
+ // validation of vertex being in bounds will fail for all vertex buffers at an offset that's
+ // not 0 (since their last stride will go beyond the data for vertex kVertexCount -1).
+ kVertexCount + 1,
+ kInstanceCount
+ );
+
+ const vertexBuffer = t.createVertexBuffers(baseData, kVertexCount + 1, kInstanceCount)[0]
+ .buffer;
+
+ // Then we recreate test data by:
+ // 1) creating multiple "vertex buffers" that all point at the GPUBuffer above but at
+ // different offsets.
+ // 2) have multiple vertex buffer, each with one attributes that will expect a0, a1, ...
+ const testData = [];
+ const vertexBuffers = [];
+ for (let i = 0; i < vbCount; i++) {
+ vertexBuffers.push({
+ slot: i,
+ buffer: vertexBuffer,
+ vbOffset: additionalVBOffset + i * alignedFormatByteSize,
+ attributes: [],
+ });
+ testData.push({
+ ...baseData[0],
+ slot: i,
+ attributes: [{ ...baseData[0].attributes[i], offset: 0 }],
+ });
+ }
+
+ // Run the test with the modified test data.
+ const pipeline = t.makeTestPipeline(testData, kVertexCount, kInstanceCount);
+ const expectedDataBG = t.createExpectedBG(testData, pipeline);
+ t.submitRenderPass(pipeline, vertexBuffers, expectedDataBG, kVertexCount, kInstanceCount);
+ });
+
+g.test('max_buffers_and_attribs')
+ .desc(
+ `Test a vertex state that loads as many attributes and buffers as possible.
+ - For each format.
+ `
+ )
+ .params(u => u.combine('format', kVertexFormats))
+ .fn(t => {
+ const { format } = t.params;
+ const attributesPerBuffer = Math.ceil(kMaxVertexAttributes / kMaxVertexBuffers);
+ let attributesEmitted = 0;
+
+ const state = [];
+ for (let i = 0; i < kMaxVertexBuffers; i++) {
+ const attributes = [];
+ for (let j = 0; j < attributesPerBuffer && attributesEmitted < kMaxVertexAttributes; j++) {
+ attributes.push({ format, offset: 0, shaderLocation: attributesEmitted });
+ attributesEmitted++;
+ }
+ state.push({
+ slot: i,
+ stepMode: 'vertex',
+ arrayStride: 32,
+ attributes,
+ });
+ }
+ t.runTest(state);
+ });
+
+g.test('array_stride_zero')
+ .desc(
+ `Test that arrayStride 0 correctly uses the same data for all vertex/instances, while another test vertex buffer with arrayStride != 0 gets different data.
+ - Test for all formats
+ - Test for both step modes`
+ )
+ .params(u =>
+ u //
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('stepMode', ['vertex', 'instance'])
+ .expand('offset', p => {
+ const formatInfo = kVertexFormatInfo[p.format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ return new Set([
+ 0,
+ 4,
+ 8,
+ formatSize,
+ formatSize * 2,
+ kMaxVertexBufferArrayStride / 2,
+ kMaxVertexBufferArrayStride - formatSize - 4,
+ kMaxVertexBufferArrayStride - formatSize - 8,
+ kMaxVertexBufferArrayStride - formatSize,
+ kMaxVertexBufferArrayStride - formatSize * 2,
+ ]);
+ })
+ )
+ .fn(t => {
+ const { format, stepMode, offset } = t.params;
+ const kCount = 10;
+
+ // Create the stride 0 part of the test, first by faking a single vertex being drawn and
+ // then expanding the data to cover kCount vertex / instances
+ const stride0TestData = t.createTestAndPipelineData(
+ [
+ {
+ slot: 0,
+ arrayStride: 2048,
+ stepMode,
+ vbOffset: offset, // used to push data in the vertex buffer
+ attributes: [{ format, offset: 0, shaderLocation: 0 }],
+ },
+ ],
+
+ 1,
+ 1
+ )[0];
+ const stride0VertexBuffer = t.createVertexBuffers([stride0TestData], kCount, kCount)[0];
+
+ // Expand the stride0 test data to have kCount values for expectedData.
+ const originalData = stride0TestData.attributes[0].expectedData;
+ const expandedData = new ArrayBuffer(kCount * originalData.byteLength);
+ for (let i = 0; i < kCount; i++) {
+ new Uint8Array(expandedData, originalData.byteLength * i).set(new Uint8Array(originalData));
+ }
+
+ // Fixup stride0TestData to use arrayStride 0.
+ stride0TestData.attributes[0].offset = offset;
+ stride0TestData.attributes[0].expectedData = expandedData;
+ stride0TestData.attributes[0].testComponentCount *= kCount;
+ stride0TestData.arrayStride = 0;
+ stride0VertexBuffer.vbOffset = 0;
+
+ // Create the part of the state that will be varying for each vertex / instance
+ const varyingTestData = t.createTestAndPipelineData(
+ [
+ {
+ slot: 1,
+ arrayStride: 32,
+ stepMode,
+ attributes: [{ format, offset: 0, shaderLocation: 1 }],
+ },
+ ],
+
+ kCount,
+ kCount
+ )[0];
+ const varyingVertexBuffer = t.createVertexBuffers([varyingTestData], kCount, kCount)[0];
+
+ // Run the test with the merged test state.
+ const state = [stride0TestData, varyingTestData];
+ const vertexBuffers = [stride0VertexBuffer, varyingVertexBuffer];
+
+ const pipeline = t.makeTestPipeline(state, kCount, kCount);
+ const expectedDataBG = t.createExpectedBG(state, pipeline);
+ t.submitRenderPass(pipeline, vertexBuffers, expectedDataBG, kCount, kCount);
+ });
+
+g.test('discontiguous_location_and_attribs')
+ .desc('Test that using far away slots / shaderLocations works as expected')
+ .fn(t => {
+ t.runTest([
+ {
+ slot: kMaxVertexBuffers - 1,
+ arrayStride: 4,
+ stepMode: 'vertex',
+ attributes: [
+ { format: 'uint8x2', offset: 2, shaderLocation: 0 },
+ { format: 'uint8x2', offset: 0, shaderLocation: 8 },
+ ],
+ },
+ {
+ slot: 1,
+ arrayStride: 16,
+ stepMode: 'instance',
+ vbOffset: 1000,
+ attributes: [{ format: 'uint32x4', offset: 0, shaderLocation: kMaxVertexAttributes - 1 }],
+ },
+ ]);
+ });
+
+g.test('overlapping_attributes')
+ .desc(
+ `Test that overlapping attributes in the same vertex buffer works
+ - Test for all formats`
+ )
+ .params(u => u.combine('format', kVertexFormats))
+ .fn(t => {
+ const { format } = t.params;
+
+ const attributes = [];
+ for (let i = 0; i < kMaxVertexAttributes; i++) {
+ attributes.push({ format, offset: 0, shaderLocation: i });
+ }
+
+ t.runTest([
+ {
+ slot: 0,
+ stepMode: 'vertex',
+ arrayStride: 32,
+ attributes,
+ },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/index_format.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/index_format.spec.js
new file mode 100644
index 0000000000..5e06d0705d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/operation/vertex_state/index_format.spec.js
@@ -0,0 +1,573 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test indexing, index format and primitive restart.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { getTextureCopyLayout } from '../../../util/texture/layout.js';
+
+const kHeight = 4;
+const kWidth = 8;
+const kTextureFormat = 'r8uint';
+
+/** 4x4 grid of r8uint values (each 0 or 1). */
+
+/** Expected 4x4 rasterization of a bottom-left triangle. */
+const kBottomLeftTriangle = [
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 1, 0, 0, 0],
+ [0, 0, 0, 0, 1, 1, 0, 0],
+ [0, 0, 0, 0, 1, 1, 1, 0],
+];
+
+/** Expected 4x4 rasterization filling the whole quad. */
+const kSquare = [
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+];
+
+/** Expected 4x4 rasterization with no pixels. */
+const kNothing = [
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+];
+
+const { byteLength, bytesPerRow, rowsPerImage } = getTextureCopyLayout(kTextureFormat, '2d', [
+ kWidth,
+ kHeight,
+ 1,
+]);
+
+class IndexFormatTest extends GPUTest {
+ MakeRenderPipeline(topology, stripIndexFormat) {
+ const vertexModule = this.device.createShaderModule({
+ // NOTE: These positions will create triangles that cut right through pixel centers. If this
+ // results in different rasterization results on different hardware, tweak to avoid this.
+ code: `
+ @vertex
+ fn main(@builtin(vertex_index) VertexIndex : u32)
+ -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 4>(
+ vec2<f32>(0.01, 0.98),
+ vec2<f32>(0.99, -0.98),
+ vec2<f32>(0.99, 0.98),
+ vec2<f32>(0.01, -0.98));
+
+ if (VertexIndex == 0xFFFFu || VertexIndex == 0xFFFFFFFFu) {
+ return vec4<f32>(-0.99, -0.98, 0.0, 1.0);
+ }
+ return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ }
+ `,
+ });
+
+ const fragmentModule = this.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) u32 {
+ return 1u;
+ }
+ `,
+ });
+
+ return this.device.createRenderPipeline({
+ layout: this.device.createPipelineLayout({ bindGroupLayouts: [] }),
+ vertex: { module: vertexModule, entryPoint: 'main' },
+ fragment: {
+ module: fragmentModule,
+ entryPoint: 'main',
+ targets: [{ format: kTextureFormat }],
+ },
+ primitive: {
+ topology,
+ stripIndexFormat,
+ },
+ });
+ }
+
+ CreateIndexBuffer(indices, indexFormat) {
+ const typedArrayConstructor = { uint16: Uint16Array, uint32: Uint32Array }[indexFormat];
+ return this.makeBufferWithContents(new typedArrayConstructor(indices), GPUBufferUsage.INDEX);
+ }
+
+ run(indexBuffer, indexCount, indexFormat, indexOffset = 0, primitiveTopology = 'triangle-list') {
+ let pipeline;
+ // The indexFormat must be set in render pipeline descriptor that specifies a strip primitive
+ // topology for primitive restart testing
+ if (primitiveTopology === 'line-strip' || primitiveTopology === 'triangle-strip') {
+ pipeline = this.MakeRenderPipeline(primitiveTopology, indexFormat);
+ } else {
+ pipeline = this.MakeRenderPipeline(primitiveTopology);
+ }
+
+ const colorAttachment = this.device.createTexture({
+ format: kTextureFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const result = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.setIndexBuffer(indexBuffer, indexFormat, indexOffset);
+ pass.drawIndexed(indexCount);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment },
+ { buffer: result, bytesPerRow, rowsPerImage },
+ [kWidth, kHeight]
+ );
+
+ this.device.queue.submit([encoder.finish()]);
+
+ return result;
+ }
+
+ CreateExpectedUint8Array(renderShape) {
+ const arrayBuffer = new Uint8Array(byteLength);
+ for (let row = 0; row < renderShape.length; row++) {
+ for (let col = 0; col < renderShape[row].length; col++) {
+ const texel = renderShape[row][col];
+
+ const kBytesPerTexel = 1; // r8uint
+ const byteOffset = row * bytesPerRow + col * kBytesPerTexel;
+ arrayBuffer[byteOffset] = texel;
+ }
+ }
+ return arrayBuffer;
+ }
+}
+
+export const g = makeTestGroup(IndexFormatTest);
+
+g.test('index_format,uint16')
+ .desc('Test rendering result of indexed draw with index format of uint16.')
+ .paramsSubcasesOnly([
+ { indexOffset: 0, _indexCount: 10, _expectedShape: kSquare },
+ { indexOffset: 6, _indexCount: 6, _expectedShape: kBottomLeftTriangle },
+ { indexOffset: 18, _indexCount: 0, _expectedShape: kNothing },
+ ])
+ .fn(t => {
+ const { indexOffset, _indexCount, _expectedShape } = t.params;
+
+ // If this is written as uint16 but interpreted as uint32, it will have index 1 and 2 be both 0
+ // and render nothing.
+ // And the index buffer size - offset must be not less than the size required by triangle
+ // list, otherwise it also render nothing.
+ const indices = [1, 2, 0, 0, 0, 0, 0, 1, 3, 0];
+ const indexBuffer = t.CreateIndexBuffer(indices, 'uint16');
+ const result = t.run(indexBuffer, _indexCount, 'uint16', indexOffset);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(_expectedShape);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
+
+g.test('index_format,uint32')
+ .desc('Test rendering result of indexed draw with index format of uint32.')
+ .paramsSubcasesOnly([
+ { indexOffset: 0, _indexCount: 10, _expectedShape: kSquare },
+ { indexOffset: 12, _indexCount: 7, _expectedShape: kBottomLeftTriangle },
+ { indexOffset: 36, _indexCount: 0, _expectedShape: kNothing },
+ ])
+ .fn(t => {
+ const { indexOffset, _indexCount, _expectedShape } = t.params;
+
+ // If this is interpreted as uint16, then it would be 0, 1, 0, ... and would draw nothing.
+ // And the index buffer size - offset must be not less than the size required by triangle
+ // list, otherwise it also render nothing.
+ const indices = [1, 2, 0, 0, 0, 0, 0, 1, 3, 0];
+ const indexBuffer = t.CreateIndexBuffer(indices, 'uint32');
+ const result = t.run(indexBuffer, _indexCount, 'uint32', indexOffset);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(_expectedShape);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
+
+g.test('index_format,change_pipeline_after_setIndexBuffer')
+ .desc('Test that setting the index buffer before the pipeline works correctly.')
+ .params(u => u.combine('setPipelineBeforeSetIndexBuffer', [false, true]))
+ .fn(t => {
+ const indexOffset = 12;
+ const indexCount = 7;
+ const expectedShape = kBottomLeftTriangle;
+
+ const indexFormat16 = 'uint16';
+ const indexFormat32 = 'uint32';
+
+ const indices = [1, 2, 0, 0, 0, 0, 0, 1, 3, 0];
+ const indexBuffer = t.CreateIndexBuffer(indices, indexFormat32);
+
+ const kPrimitiveTopology = 'triangle-strip';
+ const pipeline32 = t.MakeRenderPipeline(kPrimitiveTopology, indexFormat32);
+ const pipeline16 = t.MakeRenderPipeline(kPrimitiveTopology, indexFormat16);
+
+ const colorAttachment = t.device.createTexture({
+ format: kTextureFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const result = t.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ if (t.params.setPipelineBeforeSetIndexBuffer) {
+ pass.setPipeline(pipeline16);
+ }
+ pass.setIndexBuffer(indexBuffer, indexFormat32, indexOffset);
+ pass.setPipeline(pipeline32); // Set the pipeline for 'indexFormat32' again.
+ pass.drawIndexed(indexCount);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment },
+ { buffer: result, bytesPerRow, rowsPerImage },
+ [kWidth, kHeight]
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(expectedShape);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
+
+g.test('index_format,setIndexBuffer_before_setPipeline')
+ .desc('Test that setting the index buffer before the pipeline works correctly.')
+ .params(u => u.combine('setIndexBufferBeforeSetPipeline', [false, true]))
+ .fn(t => {
+ const indexOffset = 12;
+ const indexCount = 7;
+ const expectedShape = kBottomLeftTriangle;
+
+ const indexFormat = 'uint32';
+
+ const indices = [1, 2, 0, 0, 0, 0, 0, 1, 3, 0];
+ const indexBuffer = t.CreateIndexBuffer(indices, indexFormat);
+
+ const kPrimitiveTopology = 'triangle-strip';
+ const pipeline = t.MakeRenderPipeline(kPrimitiveTopology, indexFormat);
+
+ const colorAttachment = t.device.createTexture({
+ format: kTextureFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const result = t.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ if (t.params.setIndexBufferBeforeSetPipeline) {
+ pass.setIndexBuffer(indexBuffer, indexFormat, indexOffset);
+ pass.setPipeline(pipeline);
+ } else {
+ pass.setPipeline(pipeline);
+ pass.setIndexBuffer(indexBuffer, indexFormat, indexOffset);
+ }
+
+ pass.drawIndexed(indexCount);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment },
+ { buffer: result, bytesPerRow, rowsPerImage },
+ [kWidth, kHeight]
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(expectedShape);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
+
+g.test('index_format,setIndexBuffer_different_formats')
+ .desc(
+ `
+ Test that index buffers of multiple formats can be used with a pipeline that doesn't use strip
+ primitive topology.
+ `
+ )
+ .fn(t => {
+ const indices = [1, 2, 0, 0, 0, 0, 0, 1, 3, 0];
+
+ // Create a pipeline to be used by different index formats.
+ const kPrimitiveTopology = 'triangle-list';
+ const pipeline = t.MakeRenderPipeline(kPrimitiveTopology);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(kBottomLeftTriangle);
+
+ const colorAttachment = t.device.createTexture({
+ format: kTextureFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const result = t.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ let encoder = t.device.createCommandEncoder();
+ {
+ const indexFormat = 'uint32';
+ const indexOffset = 12;
+ const indexCount = 7;
+ const indexBuffer = t.CreateIndexBuffer(indices, indexFormat);
+
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ pass.setIndexBuffer(indexBuffer, indexFormat, indexOffset);
+ pass.setPipeline(pipeline);
+ pass.drawIndexed(indexCount);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment },
+ { buffer: result, bytesPerRow, rowsPerImage },
+ [kWidth, kHeight]
+ );
+ }
+ t.device.queue.submit([encoder.finish()]);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+
+ // Call setIndexBuffer with the pipeline and a different index format buffer.
+ encoder = t.device.createCommandEncoder();
+ {
+ const indexFormat = 'uint16';
+ const indexOffset = 6;
+ const indexCount = 6;
+ const indexBuffer = t.CreateIndexBuffer(indices, indexFormat);
+
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ pass.setIndexBuffer(indexBuffer, indexFormat, indexOffset);
+ pass.setPipeline(pipeline);
+ pass.drawIndexed(indexCount);
+ pass.end();
+ encoder.copyTextureToBuffer(
+ { texture: colorAttachment },
+ { buffer: result, bytesPerRow, rowsPerImage },
+ [kWidth, kHeight]
+ );
+ }
+ t.device.queue.submit([encoder.finish()]);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
+
+g.test('primitive_restart')
+ .desc(
+ `
+Test primitive restart with each primitive topology.
+
+Primitive restart should be always active with strip primitive topologies
+('line-strip' or 'triangle-strip') and never active for other topologies, where
+the primitive restart value isn't special and should be treated as a regular index value.
+
+The value -1 gets uploaded as 0xFFFF or 0xFFFF_FFFF according to the format.
+
+The positions of these points are embedded in the shader above, and look like this:
+ | 0 2|
+ | |
+ -1 3 1|
+
+Below are the indices lists used for each test, and the expected rendering result of each
+(approximately, in the case of incorrect results). This shows the expected result (marked '->')
+is different from what you would get if the topology were incorrect.
+
+- primitiveTopology: triangle-list
+ indices: [0, 1, 3, -1, 2, 1, 0, 0],
+ -> triangle-list: (0, 1, 3), (-1, 2, 1)
+ | # #|
+ | ####|
+ | #####|
+ | #######|
+ triangle-list with restart: (0, 1, 3), (2, 1, 0)
+ triangle-strip: (0, 1, 3), (2, 1, 0), (1, 0, 0)
+ | ####|
+ | ####|
+ | ####|
+ | ####|
+ triangle-strip w/o restart: (0, 1, 3), (1, 3, -1), (3, -1, 2), (-1, 2, 1), (2, 1, 0), (1, 0, 0)
+ | ####|
+ | ####|
+ | #####|
+ | #######|
+
+- primitiveTopology: triangle-strip
+ indices: [3, 1, 0, -1, 2, 2, 1, 3],
+ -> triangle-strip: (3, 1, 0), (2, 2, 1), (2, 1, 3)
+ | # #|
+ | ####|
+ | ####|
+ | ####|
+ triangle-strip w/o restart: (3, 1, 0), (1, 0, -1), (0, -1, 2), (2, 2, 1), (2, 3, 1)
+ | ####|
+ | #####|
+ | ######|
+ | #######|
+ triangle-list: (3, 1, 0), (-1, 2, 2)
+ triangle-list with restart: (3, 1, 0), (2, 2, 1)
+ | |
+ | # |
+ | ## |
+ | ### |
+
+- primitiveTopology: point, line-list, line-strip:
+ indices: [0, 1, -1, 2, -1, 2, 3, 0],
+ -> point-list: (0), (1), (-1), (2), (3), (0)
+ | # #|
+ | |
+ | |
+ |# # #|
+ point-list with restart (0), (1), (2), (3), (0)
+ | # #|
+ | |
+ | |
+ | # #|
+ -> line-list: (0, 1), (-1, 2), (3, 0)
+ | # ##|
+ | ## |
+ | ### # |
+ |## # #|
+ line-list with restart: (0, 1), (2, 3)
+ | # #|
+ | ## |
+ | ## |
+ | # #|
+ -> line-strip: (0, 1), (2, 3), (3, 0)
+ | # #|
+ | ### |
+ | ### |
+ | # #|
+ line-strip w/o restart: (0, 1), (1, -1), (-1, 2), (2, 3), (3, 3)
+ | # ##|
+ | ### |
+ | ## ## |
+ |########|
+`
+ )
+ .params(u =>
+ u //
+ .combine('indexFormat', ['uint16', 'uint32'])
+ .combineWithParams([
+ {
+ primitiveTopology: 'point-list',
+ _indices: [0, 1, -1, 2, 3, 0],
+ _expectedShape: [
+ [0, 0, 0, 0, 1, 0, 0, 1],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 1, 0, 0, 1],
+ ],
+ },
+ {
+ primitiveTopology: 'line-list',
+ _indices: [0, 1, -1, 2, 3, 0],
+ _expectedShape: [
+ [0, 0, 0, 0, 1, 0, 1, 1],
+ [0, 0, 0, 0, 1, 1, 0, 0],
+ [0, 0, 1, 1, 1, 0, 1, 0],
+ [1, 1, 0, 0, 1, 0, 0, 1],
+ ],
+ },
+ {
+ primitiveTopology: 'line-strip',
+ _indices: [0, 1, -1, 2, 3, 0],
+ _expectedShape: [
+ [0, 0, 0, 0, 1, 0, 0, 1],
+ [0, 0, 0, 0, 1, 1, 1, 0],
+ [0, 0, 0, 0, 1, 1, 1, 0],
+ [0, 0, 0, 0, 1, 0, 0, 1],
+ ],
+ },
+ {
+ primitiveTopology: 'triangle-list',
+ _indices: [0, 1, 3, -1, 2, 1, 0, 0],
+ _expectedShape: [
+ [0, 0, 0, 0, 0, 0, 0, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ [0, 0, 0, 1, 1, 1, 1, 1],
+ [0, 1, 1, 1, 1, 1, 1, 1],
+ ],
+ },
+ {
+ primitiveTopology: 'triangle-strip',
+ _indices: [3, 1, 0, -1, 2, 2, 1, 3],
+ _expectedShape: [
+ [0, 0, 0, 0, 0, 0, 0, 1],
+ [0, 0, 0, 0, 1, 0, 1, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ [0, 0, 0, 0, 1, 1, 1, 1],
+ ],
+ },
+ ])
+ )
+ .fn(t => {
+ const { indexFormat, primitiveTopology, _indices, _expectedShape } = t.params;
+
+ const indexBuffer = t.CreateIndexBuffer(_indices, indexFormat);
+ const result = t.run(indexBuffer, _indices.length, indexFormat, 0, primitiveTopology);
+
+ const expectedTextureValues = t.CreateExpectedUint8Array(_expectedShape);
+ t.expectGPUBufferValuesEqual(result, expectedTextureValues);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/create.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/create.spec.js
new file mode 100644
index 0000000000..c8a39346ed
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/create.spec.js
@@ -0,0 +1,122 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for validation in createBuffer.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import {
+ kAllBufferUsageBits,
+ kBufferSizeAlignment,
+ kBufferUsages,
+ kLimitInfo,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { kMaxSafeMultipleOf8 } from '../../../util/math.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+assert(kBufferSizeAlignment === 4);
+g.test('size')
+ .desc(
+ 'Test buffer size alignment is validated to be a multiple of 4 if mappedAtCreation is true.'
+ )
+ .params(u =>
+ u
+ .combine('mappedAtCreation', [false, true])
+ .beginSubcases()
+ .combine('size', [
+ 0,
+ kBufferSizeAlignment * 0.5,
+ kBufferSizeAlignment,
+ kBufferSizeAlignment * 1.5,
+ kBufferSizeAlignment * 2,
+ ])
+ )
+ .fn(t => {
+ const { mappedAtCreation, size } = t.params;
+ const isValid = !mappedAtCreation || size % kBufferSizeAlignment === 0;
+ const usage = BufferUsage.COPY_SRC;
+ t.expectGPUError(
+ 'validation',
+ () => t.device.createBuffer({ size, usage, mappedAtCreation }),
+ !isValid
+ );
+ });
+
+g.test('limit')
+ .desc('Test buffer size is validated against maxBufferSize.')
+ .params(u =>
+ u
+ .beginSubcases()
+ .combine('size', [
+ kLimitInfo.maxBufferSize.default - 1,
+ kLimitInfo.maxBufferSize.default,
+ kLimitInfo.maxBufferSize.default + 1,
+ ])
+ )
+ .fn(t => {
+ const { size } = t.params;
+ const isValid = size <= kLimitInfo.maxBufferSize.default;
+ const usage = BufferUsage.COPY_SRC;
+ t.expectGPUError('validation', () => t.device.createBuffer({ size, usage }), !isValid);
+ });
+
+const kInvalidUsage = 0x8000;
+assert((kInvalidUsage & kAllBufferUsageBits) === 0);
+g.test('usage')
+ .desc('Test combinations of zero to two usage flags are validated to be valid.')
+ .params(u =>
+ u
+ .combine('usage1', [0, ...kBufferUsages, kInvalidUsage])
+ .combine('usage2', [0, ...kBufferUsages, kInvalidUsage])
+ .beginSubcases()
+ .combine('mappedAtCreation', [false, true])
+ )
+ .fn(t => {
+ const { mappedAtCreation, usage1, usage2 } = t.params;
+ const usage = usage1 | usage2;
+
+ const isValid =
+ usage !== 0 &&
+ (usage & ~kAllBufferUsageBits) === 0 &&
+ ((usage & GPUBufferUsage.MAP_READ) === 0 ||
+ (usage & ~(GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ)) === 0) &&
+ ((usage & GPUBufferUsage.MAP_WRITE) === 0 ||
+ (usage & ~(GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE)) === 0);
+
+ t.expectGPUError(
+ 'validation',
+ () => t.device.createBuffer({ size: kBufferSizeAlignment * 2, usage, mappedAtCreation }),
+ !isValid
+ );
+ });
+
+const BufferUsage = GPUConst.BufferUsage;
+
+g.test('createBuffer_invalid_and_oom')
+ .desc(
+ `When creating a mappable buffer, it's expected that shmem may be immediately allocated
+(in the content process, before validation occurs in the GPU process). If the buffer is really
+large, though, it could fail shmem allocation before validation fails. Ensure that OOM error is
+hidden behind the "more severe" validation error.`
+ )
+ .paramsSubcasesOnly(u =>
+ u.combineWithParams([
+ { _valid: true, usage: BufferUsage.UNIFORM, size: 16 },
+ { _valid: true, usage: BufferUsage.STORAGE, size: 16 },
+ // Invalid because UNIFORM is not allowed with map usages.
+ { usage: BufferUsage.MAP_WRITE | BufferUsage.UNIFORM, size: 16 },
+ { usage: BufferUsage.MAP_WRITE | BufferUsage.UNIFORM, size: kMaxSafeMultipleOf8 },
+ { usage: BufferUsage.MAP_WRITE | BufferUsage.UNIFORM, size: 0x20_0000_0000 }, // 128 GiB
+ { usage: BufferUsage.MAP_READ | BufferUsage.UNIFORM, size: 16 },
+ { usage: BufferUsage.MAP_READ | BufferUsage.UNIFORM, size: kMaxSafeMultipleOf8 },
+ { usage: BufferUsage.MAP_READ | BufferUsage.UNIFORM, size: 0x20_0000_0000 }, // 128 GiB
+ ])
+ )
+ .fn(t => {
+ const { _valid, usage, size } = t.params;
+
+ t.expectGPUError('validation', () => t.device.createBuffer({ size, usage }), !_valid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/destroy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/destroy.spec.js
new file mode 100644
index 0000000000..ec51712a70
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/destroy.spec.js
@@ -0,0 +1,102 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for GPUBuffer.destroy.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kBufferUsages } from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('all_usages')
+ .desc('Test destroying buffers of every usage type.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('usage', kBufferUsages)
+ )
+ .fn(async t => {
+ const { usage } = t.params;
+ const buf = t.device.createBuffer({
+ size: 4,
+ usage,
+ });
+
+ buf.destroy();
+ });
+
+g.test('error_buffer')
+ .desc('Test that error buffers may be destroyed without generating validation errors.')
+ .fn(async t => {
+ const buf = t.getErrorBuffer();
+ buf.destroy();
+ });
+
+g.test('twice')
+ .desc(
+ `Test that destroying a buffer more than once is allowed.
+ - Tests buffers which are mapped at creation or not
+ - Tests buffers with various usages`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('mappedAtCreation', [false, true])
+ .combineWithParams([
+ { size: 4, usage: GPUConst.BufferUsage.COPY_SRC },
+ { size: 4, usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC },
+ { size: 4, usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ },
+ ])
+ )
+ .fn(async t => {
+ const buf = t.device.createBuffer(t.params);
+
+ buf.destroy();
+ buf.destroy();
+ });
+
+g.test('while_mapped')
+ .desc(
+ `Test destroying buffers while mapped or after being unmapped.
+ - Tests {mappable, unmappable mapAtCreation, mappable mapAtCreation}
+ - Tests while {mapped, mapped at creation, unmapped}`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('mappedAtCreation', [false, true])
+ .combine('unmapBeforeDestroy', [false, true])
+ .combineWithParams([
+ { usage: GPUConst.BufferUsage.COPY_SRC },
+ { usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC },
+ { usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ },
+ {
+ usage: GPUConst.BufferUsage.MAP_WRITE | GPUConst.BufferUsage.COPY_SRC,
+ mapMode: GPUConst.MapMode.WRITE,
+ },
+ {
+ usage: GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.MAP_READ,
+ mapMode: GPUConst.MapMode.READ,
+ },
+ ])
+ .unless(p => p.mappedAtCreation === false && p.mapMode === undefined)
+ )
+ .fn(async t => {
+ const { usage, mapMode, mappedAtCreation, unmapBeforeDestroy } = t.params;
+ const buf = t.device.createBuffer({
+ size: 4,
+ usage,
+ mappedAtCreation,
+ });
+
+ if (mapMode !== undefined) {
+ if (mappedAtCreation) {
+ buf.unmap();
+ }
+ await buf.mapAsync(mapMode);
+ }
+ if (unmapBeforeDestroy) {
+ buf.unmap();
+ }
+
+ buf.destroy();
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js
new file mode 100644
index 0000000000..c61057e2f7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/mapping.spec.js
@@ -0,0 +1,1130 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for GPUBuffer.mapAsync, GPUBuffer.unmap and GPUBuffer.getMappedRange.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { attemptGarbageCollection } from '../../../../common/util/collect_garbage.js';
+import { assert, unreachable } from '../../../../common/util/util.js';
+import { kBufferUsages } from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { ValidationTest } from '../validation_test.js';
+
+class F extends ValidationTest {
+ async testMapAsyncCall(
+ expectation,
+
+ buffer,
+ mode,
+ offset,
+ size
+ ) {
+ if (expectation === 'success') {
+ const p = buffer.mapAsync(mode, offset, size);
+ await p;
+ } else {
+ let p;
+ this.expectValidationError(() => {
+ p = buffer.mapAsync(mode, offset, size);
+ }, expectation.validationError);
+ let caught = false;
+ let rejectedEarly = false;
+ // If mapAsync rejected early, microtask A will run before B.
+ // If not, B will run before A.
+ p.catch(() => {
+ // Microtask A
+ caught = true;
+ });
+ queueMicrotask(() => {
+ // Microtask B
+ rejectedEarly = caught;
+ });
+ try {
+ // This await will always complete after microtasks A and B are both done.
+ await p;
+ assert(expectation.rejectName === null, 'mapAsync unexpectedly passed');
+ } catch (ex) {
+ assert(ex instanceof Error, 'mapAsync rejected with non-error');
+ assert(expectation.rejectName === ex.name, `mapAsync rejected unexpectedly with: ${ex}`);
+ assert(
+ expectation.earlyRejection === rejectedEarly,
+ 'mapAsync rejected at an unexpected timing'
+ );
+ }
+ }
+ }
+
+ testGetMappedRangeCall(success, buffer, offset, size) {
+ if (success) {
+ const data = buffer.getMappedRange(offset, size);
+ this.expect(data instanceof ArrayBuffer);
+ if (size !== undefined) {
+ this.expect(data.byteLength === size);
+ }
+ } else {
+ this.shouldThrow('OperationError', () => {
+ buffer.getMappedRange(offset, size);
+ });
+ }
+ }
+
+ createMappableBuffer(type, size) {
+ switch (type) {
+ case GPUMapMode.READ:
+ return this.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.MAP_READ,
+ });
+ case GPUMapMode.WRITE:
+ return this.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.MAP_WRITE,
+ });
+ default:
+ unreachable();
+ }
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kMapModeOptions = [GPUConst.MapMode.READ, GPUConst.MapMode.WRITE];
+const kOffsetAlignment = 8;
+const kSizeAlignment = 4;
+
+g.test('mapAsync,usage')
+ .desc(
+ `Test the usage validation for mapAsync.
+
+ For each buffer usage:
+ For GPUMapMode.READ, GPUMapMode.WRITE, and 0:
+ Test that the mapAsync call is valid iff the mapping usage is not 0 and the buffer usage
+ the mapMode flag.`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combineWithParams([
+ { mapMode: GPUConst.MapMode.READ, validUsage: GPUConst.BufferUsage.MAP_READ },
+ { mapMode: GPUConst.MapMode.WRITE, validUsage: GPUConst.BufferUsage.MAP_WRITE },
+ // Using mapMode 0 is never valid, so there is no validUsage.
+ { mapMode: 0, validUsage: null },
+ ])
+ .combine('usage', kBufferUsages)
+ )
+ .fn(async t => {
+ const { mapMode, validUsage, usage } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ const successParam =
+ usage === validUsage
+ ? 'success'
+ : {
+ validationError: true,
+ earlyRejection: false,
+ rejectName: 'OperationError',
+ };
+ await t.testMapAsyncCall(successParam, buffer, mapMode);
+ });
+
+g.test('mapAsync,invalidBuffer')
+ .desc('Test that mapAsync is an error when called on an invalid buffer.')
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.getErrorBuffer();
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+ });
+
+g.test('mapAsync,state,destroyed')
+ .desc('Test that mapAsync is an error when called on a destroyed buffer.')
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ // Start mapping the buffer, we are going to destroy it before it resolves so it will reject
+ // the mapping promise with an AbortError.
+ const pending = t.testMapAsyncCall(
+ { validationError: false, earlyRejection: false, rejectName: 'AbortError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.destroy();
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ await pending;
+ });
+
+g.test('mapAsync,state,mappedAtCreation')
+ .desc(
+ `Test that mapAsync is an error when called on a buffer mapped at creation,
+ but succeeds after unmapping it.`
+ )
+ .paramsSubcasesOnly([
+ { mapMode: GPUConst.MapMode.READ, validUsage: GPUConst.BufferUsage.MAP_READ },
+ { mapMode: GPUConst.MapMode.WRITE, validUsage: GPUConst.BufferUsage.MAP_WRITE },
+ ])
+ .fn(async t => {
+ const { mapMode, validUsage } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: validUsage,
+ mappedAtCreation: true,
+ });
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.unmap();
+ await t.testMapAsyncCall('success', buffer, mapMode);
+ });
+
+g.test('mapAsync,state,mapped')
+ .desc(
+ `Test that mapAsync is an error when called on a mapped buffer, but succeeds
+ after unmapping it.`
+ )
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+
+ const buffer = t.createMappableBuffer(mapMode, 16);
+ await t.testMapAsyncCall('success', buffer, mapMode);
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.unmap();
+ await t.testMapAsyncCall('success', buffer, mapMode);
+ });
+
+g.test('mapAsync,state,mappingPending')
+ .desc(
+ `Test that mapAsync is rejected when called on a buffer that is being mapped,
+ but succeeds after the previous mapping request is cancelled.`
+ )
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ // Start mapping the buffer, we are going to unmap it before it resolves so it will reject
+ // the mapping promise with an AbortError.
+ const pending0 = t.testMapAsyncCall(
+ { validationError: false, earlyRejection: false, rejectName: 'AbortError' },
+ buffer,
+ mapMode
+ );
+
+ // Do the test of mapAsync while [[pending_map]] is non-null. It has to be synchronous so
+ // that we can unmap the previous mapping in the same stack frame and testing this one doesn't
+ // get canceled, but instead is rejected.
+ const pending1 = t.testMapAsyncCall(
+ { validationError: false, earlyRejection: true, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ // Unmap the first mapping. It should now be possible to successfully call mapAsync
+ // This unmap should cause the first mapAsync rejection.
+ buffer.unmap();
+ await t.testMapAsyncCall('success', buffer, mapMode);
+
+ await pending0;
+ await pending1;
+ });
+
+g.test('mapAsync,sizeUnspecifiedOOB')
+ .desc(
+ `Test that mapAsync with size unspecified rejects if offset > buffer.[[size]],
+ with various cases at the limits of the buffer size or with a misaligned offset.
+ Also test for an empty buffer.`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('mapMode', kMapModeOptions)
+ .combineWithParams([
+ // 0 size buffer.
+ { bufferSize: 0, offset: 0 },
+ { bufferSize: 0, offset: 1 },
+ { bufferSize: 0, offset: kOffsetAlignment },
+
+ // Test with a buffer that's not empty.
+ { bufferSize: 16, offset: 0 },
+ { bufferSize: 16, offset: kOffsetAlignment },
+ { bufferSize: 16, offset: 16 },
+ { bufferSize: 16, offset: 17 },
+ { bufferSize: 16, offset: 16 + kOffsetAlignment },
+ ])
+ )
+ .fn(async t => {
+ const { mapMode, bufferSize, offset } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+
+ const successParam =
+ offset <= bufferSize
+ ? 'success'
+ : {
+ validationError: true,
+ earlyRejection: false,
+ rejectName: 'OperationError',
+ };
+ await t.testMapAsyncCall(successParam, buffer, mapMode, offset);
+ });
+
+g.test('mapAsync,offsetAndSizeAlignment')
+ .desc("Test that mapAsync fails if the alignment of offset and size isn't correct.")
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('mapMode', kMapModeOptions)
+ .combine('offset', [0, kOffsetAlignment, kOffsetAlignment / 2])
+ .combine('size', [0, kSizeAlignment, kSizeAlignment / 2])
+ )
+ .fn(async t => {
+ const { mapMode, offset, size } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ const successParam =
+ offset % kOffsetAlignment === 0 && size % kSizeAlignment === 0
+ ? 'success'
+ : {
+ validationError: true,
+ earlyRejection: false,
+ rejectName: 'OperationError',
+ };
+ await t.testMapAsyncCall(successParam, buffer, mapMode, offset, size);
+ });
+
+g.test('mapAsync,offsetAndSizeOOB')
+ .desc('Test that mapAsync fails if offset + size is larger than the buffer size.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('mapMode', kMapModeOptions)
+ .combineWithParams([
+ // For a 0 size buffer
+ { bufferSize: 0, offset: 0, size: 0 },
+ { bufferSize: 0, offset: 0, size: 4 },
+ { bufferSize: 0, offset: 8, size: 0 },
+
+ // For a small buffer
+ { bufferSize: 16, offset: 0, size: 16 },
+ { bufferSize: 16, offset: kOffsetAlignment, size: 16 },
+
+ { bufferSize: 16, offset: 16, size: 0 },
+ { bufferSize: 16, offset: 16, size: kSizeAlignment },
+
+ { bufferSize: 16, offset: 8, size: 0 },
+ { bufferSize: 16, offset: 8, size: 8 },
+ { bufferSize: 16, offset: 8, size: 8 + kSizeAlignment },
+
+ // For a larger buffer
+ { bufferSize: 1024, offset: 0, size: 1024 },
+ { bufferSize: 1024, offset: kOffsetAlignment, size: 1024 },
+
+ { bufferSize: 1024, offset: 1024, size: 0 },
+ { bufferSize: 1024, offset: 1024, size: kSizeAlignment },
+
+ { bufferSize: 1024, offset: 512, size: 0 },
+ { bufferSize: 1024, offset: 512, size: 512 },
+ { bufferSize: 1024, offset: 512, size: 512 + kSizeAlignment },
+ ])
+ )
+ .fn(async t => {
+ const { mapMode, bufferSize, size, offset } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+
+ const successParam =
+ offset + size <= bufferSize
+ ? 'success'
+ : {
+ validationError: true,
+ earlyRejection: false,
+ rejectName: 'OperationError',
+ };
+ await t.testMapAsyncCall(successParam, buffer, mapMode, offset, size);
+ });
+
+g.test('mapAsync,earlyRejection')
+ .desc("Test that mapAsync fails immediately if it's pending map.")
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions).combine('offset2', [0, 8]))
+ .fn(async t => {
+ const { mapMode, offset2 } = t.params;
+
+ const bufferSize = 16;
+ const mapSize = 8;
+ const offset1 = 0;
+
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+ const p1 = buffer.mapAsync(mapMode, offset1, mapSize); // succeeds
+ await t.testMapAsyncCall(
+ {
+ validationError: false,
+ earlyRejection: true,
+ rejectName: 'OperationError',
+ },
+ buffer,
+ mapMode,
+ offset2,
+ mapSize
+ );
+
+ await p1; // ensure the original map still succeeds
+ });
+
+g.test('mapAsync,abort_over_invalid_error')
+ .desc(
+ `Test that unmap abort error should have precedence over validation error
+TODO
+ - Add other validation error test (eg. offset is not a multiple of 8)
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('mapMode', kMapModeOptions).combine('unmapBeforeResolve', [true, false])
+ )
+ .fn(async t => {
+ const { mapMode, unmapBeforeResolve } = t.params;
+ const bufferSize = 8;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+ await buffer.mapAsync(mapMode);
+
+ if (unmapBeforeResolve) {
+ // unmap abort error should have precedence over validation error
+ const pending = t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'AbortError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.unmap();
+ await pending;
+ } else {
+ // map on already mapped buffer should cause validation error
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.unmap();
+ }
+ });
+
+g.test('getMappedRange,state,mapped')
+ .desc('Test that it is valid to call getMappedRange in the mapped state')
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const bufferSize = 16;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+ await buffer.mapAsync(mapMode);
+
+ const data = buffer.getMappedRange();
+ t.expect(data instanceof ArrayBuffer);
+ t.expect(data.byteLength === bufferSize);
+
+ // map on already mapped buffer should be rejected
+ const pending = t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ t.expect(data.byteLength === bufferSize);
+ await pending;
+
+ buffer.unmap();
+
+ t.expect(data.byteLength === 0);
+ });
+
+g.test('getMappedRange,state,mappedAtCreation')
+ .desc(
+ `Test that, in the mapped-at-creation state, it is valid to call getMappedRange, for all buffer usages,
+ and invalid to call mapAsync, for all map modes.`
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('bufferUsage', kBufferUsages).combine('mapMode', kMapModeOptions)
+ )
+ .fn(async t => {
+ const { bufferUsage, mapMode } = t.params;
+ const bufferSize = 16;
+ const buffer = t.device.createBuffer({
+ usage: bufferUsage,
+ size: bufferSize,
+ mappedAtCreation: true,
+ });
+
+ const data = buffer.getMappedRange();
+ t.expect(data instanceof ArrayBuffer);
+ t.expect(data.byteLength === bufferSize);
+
+ // map on already mapped buffer should be rejected
+ const pending = t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ t.expect(data.byteLength === bufferSize);
+ await pending;
+
+ buffer.unmap();
+
+ t.expect(data.byteLength === 0);
+ });
+
+g.test('getMappedRange,state,invalid_mappedAtCreation')
+ .desc(
+ `mappedAtCreation should return a mapped buffer, even if the buffer is invalid.
+Like VRAM allocation (see map_oom), validation can be performed asynchronously (in the GPU process)
+so the Content process doesn't necessarily know the buffer is invalid.`
+ )
+ .fn(async t => {
+ const buffer = t.expectGPUError('validation', () =>
+ t.device.createBuffer({
+ mappedAtCreation: true,
+ size: 16,
+ usage: 0xffff_ffff, // Invalid usage
+ })
+ );
+
+ // Should still be valid.
+ buffer.getMappedRange();
+ });
+
+g.test('getMappedRange,state,mappedAgain')
+ .desc(
+ 'Test that it is valid to call getMappedRange in the mapped state, even if there is a duplicate mapAsync before'
+ )
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+ await buffer.mapAsync(mapMode);
+
+ // call mapAsync again on already mapped buffer should fail
+ await t.testMapAsyncCall(
+ { validationError: true, earlyRejection: false, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ // getMapppedRange should still success
+ t.testGetMappedRangeCall(true, buffer);
+ });
+
+g.test('getMappedRange,state,unmapped')
+ .desc(
+ `Test that it is invalid to call getMappedRange in the unmapped state.
+Test for various cases of being unmapped: at creation, after a mapAsync call or after being created mapped.`
+ )
+ .fn(async t => {
+ // It is invalid to call getMappedRange when the buffer starts unmapped when created.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ t.testGetMappedRangeCall(false, buffer);
+ }
+
+ // It is invalid to call getMappedRange when the buffer is unmapped after mapAsync.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ await buffer.mapAsync(GPUMapMode.READ);
+ buffer.unmap();
+ t.testGetMappedRangeCall(false, buffer);
+ }
+
+ // It is invalid to call getMappedRange when the buffer is unmapped after mappedAtCreation.
+ {
+ const buffer = t.device.createBuffer({
+ usage: GPUBufferUsage.MAP_READ,
+ size: 16,
+ mappedAtCreation: true,
+ });
+ buffer.unmap();
+ t.testGetMappedRangeCall(false, buffer);
+ }
+ });
+
+g.test('getMappedRange,subrange,mapped')
+ .desc(
+ `Test that old getMappedRange returned arraybuffer does not exist after unmap, and newly returned
+ arraybuffer after new map has correct subrange`
+ )
+ .params(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const bufferSize = 16;
+ const offset = 8;
+ const subrangeSize = bufferSize - offset;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+ await buffer.mapAsync(mapMode);
+
+ const data0 = buffer.getMappedRange();
+ t.expect(data0 instanceof ArrayBuffer);
+ t.expect(data0.byteLength === bufferSize);
+
+ buffer.unmap();
+ t.expect(data0.byteLength === 0);
+
+ await buffer.mapAsync(mapMode, offset);
+ const data1 = buffer.getMappedRange(8);
+
+ t.expect(data0.byteLength === 0);
+ t.expect(data1.byteLength === subrangeSize);
+ });
+
+g.test('getMappedRange,subrange,mappedAtCreation')
+ .desc(
+ `Test that old getMappedRange returned arraybuffer does not exist after unmap and newly returned
+ arraybuffer after new map has correct subrange`
+ )
+ .fn(async t => {
+ const bufferSize = 16;
+ const offset = 8;
+ const subrangeSize = bufferSize - offset;
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ mappedAtCreation: true,
+ });
+
+ const data0 = buffer.getMappedRange();
+ t.expect(data0 instanceof ArrayBuffer);
+ t.expect(data0.byteLength === bufferSize);
+
+ buffer.unmap();
+ t.expect(data0.byteLength === 0);
+
+ await buffer.mapAsync(GPUMapMode.READ, offset);
+ const data1 = buffer.getMappedRange(8);
+
+ t.expect(data0.byteLength === 0);
+ t.expect(data1.byteLength === subrangeSize);
+ });
+
+g.test('getMappedRange,state,destroyed')
+ .desc(
+ `Test that it is invalid to call getMappedRange in the destroyed state.
+Test for various cases of being destroyed: at creation, after a mapAsync call or after being created mapped.`
+ )
+ .fn(async t => {
+ // It is invalid to call getMappedRange when the buffer is destroyed when unmapped.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ buffer.destroy();
+ t.testGetMappedRangeCall(false, buffer);
+ }
+
+ // It is invalid to call getMappedRange when the buffer is destroyed when mapped.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ await buffer.mapAsync(GPUMapMode.READ);
+ buffer.destroy();
+ t.testGetMappedRangeCall(false, buffer);
+ }
+
+ // It is invalid to call getMappedRange when the buffer is destroyed when mapped at creation.
+ {
+ const buffer = t.device.createBuffer({
+ usage: GPUBufferUsage.MAP_READ,
+ size: 16,
+ mappedAtCreation: true,
+ });
+ buffer.destroy();
+ t.testGetMappedRangeCall(false, buffer);
+ }
+ });
+
+g.test('getMappedRange,state,mappingPending')
+ .desc(`Test that it is invalid to call getMappedRange in the mappingPending state.`)
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ /* noawait */ const mapping0 = buffer.mapAsync(mapMode);
+ // seconding mapping should be rejected
+ const mapping1 = t.testMapAsyncCall(
+ { validationError: false, earlyRejection: true, rejectName: 'OperationError' },
+ buffer,
+ mapMode
+ );
+
+ // invalid in mappingPending state
+ t.testGetMappedRangeCall(false, buffer);
+
+ await mapping0;
+
+ // valid after buffer is mapped
+ t.testGetMappedRangeCall(true, buffer);
+
+ await mapping1;
+ });
+
+g.test('getMappedRange,offsetAndSizeAlignment,mapped')
+ .desc(`Test that getMappedRange fails if the alignment of offset and size isn't correct.`)
+ .params(u =>
+ u
+ .combine('mapMode', kMapModeOptions)
+ .beginSubcases()
+ .combine('mapOffset', [0, kOffsetAlignment])
+ .combine('offset', [0, kOffsetAlignment, kOffsetAlignment / 2])
+ .combine('size', [0, kSizeAlignment, kSizeAlignment / 2])
+ )
+ .fn(async t => {
+ const { mapMode, mapOffset, offset, size } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 32);
+ await buffer.mapAsync(mapMode, mapOffset);
+
+ const success = offset % kOffsetAlignment === 0 && size % kSizeAlignment === 0;
+ t.testGetMappedRangeCall(success, buffer, offset + mapOffset, size);
+ });
+
+g.test('getMappedRange,offsetAndSizeAlignment,mappedAtCreation')
+ .desc(`Test that getMappedRange fails if the alignment of offset and size isn't correct.`)
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('offset', [0, kOffsetAlignment, kOffsetAlignment / 2])
+ .combine('size', [0, kSizeAlignment, kSizeAlignment / 2])
+ )
+ .fn(async t => {
+ const { offset, size } = t.params;
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ mappedAtCreation: true,
+ });
+ const success = offset % kOffsetAlignment === 0 && size % kSizeAlignment === 0;
+ t.testGetMappedRangeCall(success, buffer, offset, size);
+ });
+
+g.test('getMappedRange,sizeAndOffsetOOB,mappedAtCreation')
+ .desc(
+ `Test that getMappedRange size + offset must be less than the buffer size for a
+ buffer mapped at creation. (and offset has not constraints on its own)`
+ )
+ .paramsSubcasesOnly([
+ // Tests for a zero-sized buffer, with and without a size defined.
+ { bufferSize: 0, offset: undefined, size: undefined },
+ { bufferSize: 0, offset: undefined, size: 0 },
+ { bufferSize: 0, offset: undefined, size: kSizeAlignment },
+ { bufferSize: 0, offset: 0, size: undefined },
+ { bufferSize: 0, offset: 0, size: 0 },
+ { bufferSize: 0, offset: kOffsetAlignment, size: undefined },
+ { bufferSize: 0, offset: kOffsetAlignment, size: 0 },
+
+ // Tests for a non-empty buffer, with an undefined offset.
+ { bufferSize: 80, offset: undefined, size: 80 },
+ { bufferSize: 80, offset: undefined, size: 80 + kSizeAlignment },
+
+ // Tests for a non-empty buffer, with an undefined size.
+ { bufferSize: 80, offset: undefined, size: undefined },
+ { bufferSize: 80, offset: 0, size: undefined },
+ { bufferSize: 80, offset: kOffsetAlignment, size: undefined },
+ { bufferSize: 80, offset: 80, size: undefined },
+ { bufferSize: 80, offset: 80 + kOffsetAlignment, size: undefined },
+
+ // Tests for a non-empty buffer with a size defined.
+ { bufferSize: 80, offset: 0, size: 80 },
+ { bufferSize: 80, offset: 0, size: 80 + kSizeAlignment },
+ { bufferSize: 80, offset: kOffsetAlignment, size: 80 },
+
+ { bufferSize: 80, offset: 40, size: 40 },
+ { bufferSize: 80, offset: 40 + kOffsetAlignment, size: 40 },
+ { bufferSize: 80, offset: 40, size: 40 + kSizeAlignment },
+ ])
+ .fn(t => {
+ const { bufferSize, offset, size } = t.params;
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_DST,
+ mappedAtCreation: true,
+ });
+
+ const actualOffset = offset ?? 0;
+ const actualSize = size ?? bufferSize - actualOffset;
+
+ const success = actualOffset <= bufferSize && actualOffset + actualSize <= bufferSize;
+ t.testGetMappedRangeCall(success, buffer, offset, size);
+ });
+
+g.test('getMappedRange,sizeAndOffsetOOB,mapped')
+ .desc('Test that getMappedRange size + offset must be less than the mapAsync range.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('mapMode', kMapModeOptions)
+ .combineWithParams([
+ // Tests for an empty buffer, and implicit mapAsync size.
+ { bufferSize: 0, mapOffset: 0, mapSize: undefined, offset: undefined, size: undefined },
+ { bufferSize: 0, mapOffset: 0, mapSize: undefined, offset: undefined, size: 0 },
+ {
+ bufferSize: 0,
+ mapOffset: 0,
+ mapSize: undefined,
+ offset: undefined,
+ size: kSizeAlignment,
+ },
+ { bufferSize: 0, mapOffset: 0, mapSize: undefined, offset: 0, size: undefined },
+ { bufferSize: 0, mapOffset: 0, mapSize: undefined, offset: 0, size: 0 },
+ {
+ bufferSize: 0,
+ mapOffset: 0,
+ mapSize: undefined,
+ offset: kOffsetAlignment,
+ size: undefined,
+ },
+ { bufferSize: 0, mapOffset: 0, mapSize: undefined, offset: kOffsetAlignment, size: 0 },
+
+ // Tests for an empty buffer, and explicit mapAsync size.
+ { bufferSize: 0, mapOffset: 0, mapSize: 0, offset: undefined, size: undefined },
+ { bufferSize: 0, mapOffset: 0, mapSize: 0, offset: 0, size: undefined },
+ { bufferSize: 0, mapOffset: 0, mapSize: 0, offset: 0, size: 0 },
+ { bufferSize: 0, mapOffset: 0, mapSize: 0, offset: kOffsetAlignment, size: undefined },
+ { bufferSize: 0, mapOffset: 0, mapSize: 0, offset: kOffsetAlignment, size: 0 },
+
+ // Test for a fully implicit mapAsync call
+ { bufferSize: 80, mapOffset: undefined, mapSize: undefined, offset: 0, size: 80 },
+ {
+ bufferSize: 80,
+ mapOffset: undefined,
+ mapSize: undefined,
+ offset: 0,
+ size: 80 + kSizeAlignment,
+ },
+ {
+ bufferSize: 80,
+ mapOffset: undefined,
+ mapSize: undefined,
+ offset: kOffsetAlignment,
+ size: 80,
+ },
+
+ // Test for a mapAsync call with an implicit size
+ { bufferSize: 80, mapOffset: 24, mapSize: undefined, offset: 24, size: 80 - 24 },
+ {
+ bufferSize: 80,
+ mapOffset: 24,
+ mapSize: undefined,
+ offset: 0,
+ size: 80 - 24 + kSizeAlignment,
+ },
+ {
+ bufferSize: 80,
+ mapOffset: 24,
+ mapSize: undefined,
+ offset: kOffsetAlignment,
+ size: 80 - 24,
+ },
+
+ // Test for a non-empty buffer fully mapped.
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: 0, size: 80 },
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: kOffsetAlignment, size: 80 },
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: 0, size: 80 + kSizeAlignment },
+
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: 40, size: 40 },
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: 40 + kOffsetAlignment, size: 40 },
+ { bufferSize: 80, mapOffset: 0, mapSize: 80, offset: 40, size: 40 + kSizeAlignment },
+
+ // Test for a buffer partially mapped.
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 24, size: 40 },
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 24 - kOffsetAlignment, size: 40 },
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 24 + kOffsetAlignment, size: 40 },
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 24, size: 40 + kSizeAlignment },
+
+ // Test for a partially mapped buffer with implicit size and offset for getMappedRange.
+ // - Buffer partially mapped in the middle
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: undefined, size: undefined },
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 0, size: undefined },
+ { bufferSize: 80, mapOffset: 24, mapSize: 40, offset: 24, size: undefined },
+ // - Buffer partially mapped to the end
+ { bufferSize: 80, mapOffset: 24, mapSize: undefined, offset: 24, size: undefined },
+ { bufferSize: 80, mapOffset: 24, mapSize: undefined, offset: 80, size: undefined },
+ // - Buffer partially mapped from the start
+ { bufferSize: 80, mapOffset: 0, mapSize: 64, offset: undefined, size: undefined },
+ { bufferSize: 80, mapOffset: 0, mapSize: 64, offset: undefined, size: 64 },
+ ])
+ )
+ .fn(async t => {
+ const { mapMode, bufferSize, mapOffset, mapSize, offset, size } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, bufferSize);
+ await buffer.mapAsync(mapMode, mapOffset, mapSize);
+
+ const actualMapOffset = mapOffset ?? 0;
+ const actualMapSize = mapSize ?? bufferSize - actualMapOffset;
+
+ const actualOffset = offset ?? 0;
+ const actualSize = size ?? bufferSize - actualOffset;
+
+ const success =
+ actualOffset >= actualMapOffset &&
+ actualOffset <= bufferSize &&
+ actualOffset + actualSize <= actualMapOffset + actualMapSize;
+ t.testGetMappedRangeCall(success, buffer, offset, size);
+ });
+
+g.test('getMappedRange,disjointRanges')
+ .desc('Test that the ranges asked through getMappedRange must be disjoint.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('remapBetweenCalls', [false, true])
+ .combineWithParams([
+ // Disjoint ranges with one that's empty.
+ { offset1: 8, size1: 0, offset2: 8, size2: 8 },
+ { offset1: 16, size1: 0, offset2: 8, size2: 8 },
+
+ { offset1: 8, size1: 8, offset2: 8, size2: 0 },
+ { offset1: 8, size1: 8, offset2: 16, size2: 0 },
+
+ // Disjoint ranges with both non-empty.
+ { offset1: 0, size1: 8, offset2: 8, size2: 8 },
+ { offset1: 16, size1: 8, offset2: 8, size2: 8 },
+
+ { offset1: 8, size1: 8, offset2: 0, size2: 8 },
+ { offset1: 8, size1: 8, offset2: 16, size2: 8 },
+
+ // Empty range contained inside another one.
+ { offset1: 16, size1: 20, offset2: 24, size2: 0 },
+ { offset1: 24, size1: 0, offset2: 16, size2: 20 },
+
+ // Ranges that overlap only partially.
+ { offset1: 16, size1: 20, offset2: 8, size2: 20 },
+ { offset1: 16, size1: 20, offset2: 32, size2: 20 },
+
+ // Ranges that include one another.
+ { offset1: 0, size1: 80, offset2: 16, size2: 20 },
+ { offset1: 16, size1: 20, offset2: 0, size2: 80 },
+ ])
+ )
+ .fn(async t => {
+ const { offset1, size1, offset2, size2, remapBetweenCalls } = t.params;
+ const buffer = t.device.createBuffer({ size: 80, usage: GPUBufferUsage.MAP_READ });
+ await buffer.mapAsync(GPUMapMode.READ);
+
+ t.testGetMappedRangeCall(true, buffer, offset1, size1);
+
+ if (remapBetweenCalls) {
+ buffer.unmap();
+ await buffer.mapAsync(GPUMapMode.READ);
+ }
+
+ const range1StartsAfter2 = offset1 >= offset2 + size2;
+ const range2StartsAfter1 = offset2 >= offset1 + size1;
+ const disjoint = range1StartsAfter2 || range2StartsAfter1;
+ const success = disjoint || remapBetweenCalls;
+
+ t.testGetMappedRangeCall(success, buffer, offset2, size2);
+ });
+
+g.test('getMappedRange,disjoinRanges_many')
+ .desc('Test getting a lot of small ranges, and that the disjoint check checks them all.')
+ .fn(async t => {
+ const kStride = 256;
+ const kNumStrides = 256;
+
+ const buffer = t.device.createBuffer({
+ size: kStride * kNumStrides,
+ usage: GPUBufferUsage.MAP_READ,
+ });
+ await buffer.mapAsync(GPUMapMode.READ);
+
+ // Get a lot of small mapped ranges.
+ for (let stride = 0; stride < kNumStrides; stride++) {
+ t.testGetMappedRangeCall(true, buffer, stride * kStride, 8);
+ }
+
+ // Check for each range it is invalid to get a range that overlaps it and check that it is valid
+ // to get ranges for the rest of the buffer.
+ for (let stride = 0; stride < kNumStrides; stride++) {
+ t.testGetMappedRangeCall(false, buffer, stride * kStride, kStride);
+ t.testGetMappedRangeCall(true, buffer, stride * kStride + 8, kStride - 8);
+ }
+ });
+
+g.test('unmap,state,unmapped')
+ .desc(
+ `Test it is valid to call unmap on a buffer that is unmapped (at creation, or after
+ mappedAtCreation or mapAsync)`
+ )
+ .fn(async t => {
+ // It is valid to call unmap after creation of an unmapped buffer.
+ {
+ const buffer = t.device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ });
+ buffer.unmap();
+ }
+
+ // It is valid to call unmap after unmapping a mapAsynced buffer.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ await buffer.mapAsync(GPUMapMode.READ);
+ buffer.unmap();
+ buffer.unmap();
+ }
+
+ // It is valid to call unmap after unmapping a mappedAtCreation buffer.
+ {
+ const buffer = t.device.createBuffer({
+ usage: GPUBufferUsage.MAP_READ,
+ size: 16,
+ mappedAtCreation: true,
+ });
+ buffer.unmap();
+ buffer.unmap();
+ }
+ });
+
+g.test('unmap,state,destroyed')
+ .desc(
+ `Test it is valid to call unmap on a buffer that is destroyed (at creation, or after
+ mappedAtCreation or mapAsync)`
+ )
+ .fn(async t => {
+ // It is valid to call unmap after destruction of an unmapped buffer.
+ {
+ const buffer = t.device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ });
+ buffer.destroy();
+ buffer.unmap();
+ }
+
+ // It is valid to call unmap after destroying a mapAsynced buffer.
+ {
+ const buffer = t.createMappableBuffer(GPUMapMode.READ, 16);
+ await buffer.mapAsync(GPUMapMode.READ);
+ buffer.destroy();
+ buffer.unmap();
+ }
+
+ // It is valid to call unmap after destroying a mappedAtCreation buffer.
+ {
+ const buffer = t.device.createBuffer({
+ usage: GPUBufferUsage.MAP_READ,
+ size: 16,
+ mappedAtCreation: true,
+ });
+ buffer.destroy();
+ buffer.unmap();
+ }
+ });
+
+g.test('unmap,state,mappedAtCreation')
+ .desc('Test it is valid to call unmap on a buffer mapped at creation, for various usages')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('bufferUsage', kBufferUsages)
+ )
+ .fn(t => {
+ const { bufferUsage } = t.params;
+ const buffer = t.device.createBuffer({ size: 16, usage: bufferUsage, mappedAtCreation: true });
+
+ buffer.unmap();
+ });
+
+g.test('unmap,state,mapped')
+ .desc("Test it is valid to call unmap on a buffer that's mapped")
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ await buffer.mapAsync(mapMode);
+ buffer.unmap();
+ });
+
+g.test('unmap,state,mappingPending')
+ .desc("Test it is valid to call unmap on a buffer that's being mapped")
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+ const buffer = t.createMappableBuffer(mapMode, 16);
+
+ const pending = t.testMapAsyncCall(
+ { validationError: false, earlyRejection: false, rejectName: 'AbortError' },
+ buffer,
+ mapMode
+ );
+
+ buffer.unmap();
+ await pending;
+ });
+
+g.test('gc_behavior,mappedAtCreation')
+ .desc(
+ "Test that GCing the buffer while mappings are handed out doesn't invalidate them - mappedAtCreation case"
+ )
+ .fn(async t => {
+ let buffer = null;
+ buffer = t.device.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.COPY_DST,
+ mappedAtCreation: true,
+ });
+
+ // Write some non-zero data to the buffer.
+ const contents = new Uint32Array(buffer.getMappedRange());
+ for (let i = 0; i < contents.length; i++) {
+ contents[i] = i;
+ }
+
+ // Trigger garbage collection that should collect the buffer (or as if it collected it)
+ // NOTE: This won't fail unless the browser immediately starts reusing the memory, or gives it
+ // back to the OS. One good option for browsers to check their logic is good is to zero-out the
+ // memory on GPUBuffer (or internal gpu::Buffer-like object) destruction.
+ buffer = null;
+ await attemptGarbageCollection();
+
+ // Use the mapping again both for read and write, it should work.
+ for (let i = 0; i < contents.length; i++) {
+ t.expect(contents[i] === i);
+ contents[i] = i + 1;
+ }
+ });
+
+g.test('gc_behavior,mapAsync')
+ .desc(
+ "Test that GCing the buffer while mappings are handed out doesn't invalidate them - mapAsync case"
+ )
+ .paramsSubcasesOnly(u => u.combine('mapMode', kMapModeOptions))
+ .fn(async t => {
+ const { mapMode } = t.params;
+
+ let buffer = null;
+ buffer = t.createMappableBuffer(mapMode, 256);
+ await buffer.mapAsync(mapMode);
+
+ // Write some non-zero data to the buffer.
+ const contents = new Uint32Array(buffer.getMappedRange());
+ for (let i = 0; i < contents.length; i++) {
+ contents[i] = i;
+ }
+
+ // Trigger garbage collection that should collect the buffer (or as if it collected it)
+ // NOTE: This won't fail unless the browser immediately starts reusing the memory, or gives it
+ // back to the OS. One good option for browsers to check their logic is good is to zero-out the
+ // memory on GPUBuffer (or internal gpu::Buffer-like object) destruction.
+ buffer = null;
+ await attemptGarbageCollection();
+
+ // Use the mapping again both for read and write, it should work.
+ for (let i = 0; i < contents.length; i++) {
+ t.expect(contents[i] === i);
+ contents[i] = i + 1;
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/threading.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/threading.spec.js
new file mode 100644
index 0000000000..46256ab73d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/buffer/threading.spec.js
@@ -0,0 +1,15 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- Try to map on one thread while {pending, mapped, mappedAtCreation, mappedAtCreation+unmap+mapped}
+ on another thread.
+- Invalid to postMessage a mapped range's ArrayBuffer or ArrayBufferView
+ {with, without} it being in the transfer array.
+- Copy GPUBuffer to another thread while {pending, mapped mappedAtCreation} on {same,diff} thread
+ (valid), then try to map on that thread (invalid)
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js
new file mode 100644
index 0000000000..53b7f7e510
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/query_types.spec.js
@@ -0,0 +1,77 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for capability checking for features enabling optional query types.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('createQuerySet')
+ .desc(
+ `
+ Tests that creating a query set throws a type error exception if the features don't contain
+ 'timestamp-query'.
+ - createQuerySet
+ - type {occlusion, timestamp}
+ - x= {pipeline statistics, timestamp} query {enable, disable}
+ `
+ )
+ .params(u =>
+ u
+ .combine('type', ['occlusion', 'timestamp'])
+ .combine('featureContainsTimestampQuery', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { featureContainsTimestampQuery } = t.params;
+
+ const requiredFeatures = [];
+ if (featureContainsTimestampQuery) {
+ requiredFeatures.push('timestamp-query');
+ }
+
+ t.selectDeviceOrSkipTestCase({ requiredFeatures });
+ })
+ .fn(async t => {
+ const { type, featureContainsTimestampQuery } = t.params;
+
+ const count = 1;
+ const shouldException = type === 'timestamp' && !featureContainsTimestampQuery;
+
+ t.shouldThrow(shouldException ? 'TypeError' : false, () => {
+ t.device.createQuerySet({ type, count });
+ });
+ });
+
+g.test('writeTimestamp')
+ .desc(
+ `
+ Tests that writing a timestamp throws a type error exception if the features don't contain
+ 'timestamp-query'.
+ `
+ )
+ .params(u => u.combine('featureContainsTimestampQuery', [false, true]))
+ .beforeAllSubcases(t => {
+ const { featureContainsTimestampQuery } = t.params;
+
+ const requiredFeatures = [];
+ if (featureContainsTimestampQuery) {
+ requiredFeatures.push('timestamp-query');
+ }
+
+ t.selectDeviceOrSkipTestCase({ requiredFeatures });
+ })
+ .fn(async t => {
+ const { featureContainsTimestampQuery } = t.params;
+
+ const querySet = t.device.createQuerySet({
+ type: featureContainsTimestampQuery ? 'timestamp' : 'occlusion',
+ count: 1,
+ });
+ const encoder = t.createEncoder('non-pass');
+
+ t.shouldThrow(featureContainsTimestampQuery ? false : 'TypeError', () => {
+ encoder.encoder.writeTimestamp(querySet, 0);
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/texture_formats.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/texture_formats.spec.js
new file mode 100644
index 0000000000..d3539e388e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/capability_checks/features/texture_formats.spec.js
@@ -0,0 +1,446 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for capability checking for features enabling optional texture formats.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { assert } from '../../../../../common/util/util.js';
+import { kAllTextureFormats, kTextureFormatInfo } from '../../../../capability_info.js';
+import { kAllCanvasTypes, createCanvas } from '../../../../util/create_elements.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+const kOptionalTextureFormats = kAllTextureFormats.filter(
+ t => kTextureFormatInfo[t].feature !== undefined
+);
+
+g.test('texture_descriptor')
+ .desc(
+ `
+ Test creating a texture with an optional texture format will fail if the required optional feature
+ is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createTexture({
+ format,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });
+
+g.test('texture_descriptor_view_formats')
+ .desc(
+ `
+ Test creating a texture with view formats that have an optional texture format will fail if the
+ required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createTexture({
+ format,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [format],
+ });
+ });
+ });
+
+g.test('texture_view_descriptor')
+ .desc(
+ `
+ Test creating a texture view with all texture formats will fail if the required optional feature
+ is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ // If the required feature isn't enabled then the texture will fail to create and we won't be
+ // able to test createView, so pick and alternate guaranteed format instead. This will almost
+ // certainly not be view-compatible with the format being tested, but that doesn't matter since
+ // createView should throw an exception due to the format feature not being enabled before it
+ // has a chance to validate that the view and texture formats aren't compatible.
+ const textureFormat = enable_required_feature ? format : 'rgba8unorm';
+
+ const formatInfo = kTextureFormatInfo[format];
+ const testTexture = t.device.createTexture({
+ format: textureFormat,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ const testViewDesc = {
+ format,
+ dimension: '2d',
+ aspect: 'all',
+ arrayLayerCount: 1,
+ baseMipLevel: 0,
+ mipLevelCount: 1,
+ baseArrayLayer: 0,
+ };
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ testTexture.createView(testViewDesc);
+ });
+ });
+
+g.test('canvas_configuration')
+ .desc(
+ `
+ Test configuring a canvas with optional texture formats will throw an exception if the required
+ optional feature is not enabled. Otherwise, a validation error should be generated instead of
+ throwing an exception.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, canvasType, enable_required_feature } = t.params;
+
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ const canvasConf = {
+ device: t.device,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ };
+
+ if (enable_required_feature) {
+ t.expectValidationError(() => {
+ ctx.configure(canvasConf);
+ });
+ } else {
+ t.shouldThrow('TypeError', () => {
+ ctx.configure(canvasConf);
+ });
+ }
+ });
+
+g.test('canvas_configuration_view_formats')
+ .desc(
+ `
+ Test that configuring a canvas with view formats throws an exception if the required optional
+ feature is not enabled. Otherwise, a validation error should be generated instead of throwing an
+ exception.
+ `
+ )
+ .params(u =>
+ u
+ .combine('viewFormats', [
+ ...kOptionalTextureFormats.map(format => [format]),
+ ['bgra8unorm', 'bc1-rgba-unorm'],
+ ['bc1-rgba-unorm', 'bgra8unorm'],
+ ])
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { viewFormats, enable_required_feature } = t.params;
+
+ if (enable_required_feature) {
+ t.selectDeviceForTextureFormatOrSkipTestCase(viewFormats);
+ }
+ })
+ .fn(async t => {
+ const { viewFormats, canvasType, enable_required_feature } = t.params;
+
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ const canvasConf = {
+ device: t.device,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ viewFormats: viewFormats,
+ };
+
+ if (enable_required_feature) {
+ t.expectValidationError(() => {
+ ctx.configure(canvasConf);
+ });
+ } else {
+ t.shouldThrow('TypeError', () => {
+ ctx.configure(canvasConf);
+ });
+ }
+ });
+
+g.test('storage_texture_binding_layout')
+ .desc(
+ `
+ Test creating a GPUStorageTextureBindingLayout with an optional texture format will fail if the
+ required optional feature are not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting storage.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].storage)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ storageTexture: {
+ format,
+ },
+ },
+ ],
+ });
+ });
+ });
+
+g.test('color_target_state')
+ .desc(
+ `
+ Test creating a render pipeline with an optional texture format set in GPUColorTargetState will
+ fail if the required optional feature is not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting color rendering.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ });
+ });
+ });
+
+g.test('depth_stencil_state')
+ .desc(
+ `
+ Test creating a render pipeline with an optional texture format set in GPUColorTargetState will
+ fail if the required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(
+ t =>
+ kTextureFormatInfo[t.format].renderable &&
+ (kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil)
+ )
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ depthStencil: {
+ format,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+ });
+
+g.test('render_bundle_encoder_descriptor_color_format')
+ .desc(
+ `
+ Test creating a render bundle encoder with an optional texture format set as one of the color
+ format will fail if the required optional feature is not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting color rendering.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [format],
+ });
+ });
+ });
+
+g.test('render_bundle_encoder_descriptor_depth_stencil_format')
+ .desc(
+ `
+ Test creating a render bundle encoder with an optional texture format set as the depth stencil
+ format will fail if the required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(
+ t =>
+ kTextureFormatInfo[t.format].renderable &&
+ (kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil)
+ )
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ depthStencilFormat: format,
+ });
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js
new file mode 100644
index 0000000000..a89cc61bac
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/compute_pipeline.spec.js
@@ -0,0 +1,667 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+createComputePipeline and createComputePipelineAsync validation tests.
+
+Note: entry point matching tests are in shader_module/entry_point.spec.ts
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { kValue } from '../../util/constants.js';
+import { getShaderWithEntryPoint } from '../../util/shader.js';
+
+import { ValidationTest } from './validation_test.js';
+
+class F extends ValidationTest {
+ getShaderModule(shaderStage = 'compute', entryPoint = 'main') {
+ return this.device.createShaderModule({
+ code: getShaderWithEntryPoint(shaderStage, entryPoint),
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('basic')
+ .desc(
+ `
+Control case for createComputePipeline and createComputePipelineAsync.
+Call the API with valid compute shader and matching valid entryPoint, making sure that the test function working well.
+`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const { isAsync } = t.params;
+ t.doCreateComputePipelineTest(isAsync, true, {
+ layout: 'auto',
+ compute: { module: t.getShaderModule('compute', 'main'), entryPoint: 'main' },
+ });
+ });
+
+g.test('shader_module,invalid')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) with a invalid compute shader, and check that the APIs catch this error.
+`
+ )
+ .params(u => u.combine('isAsync', [true, false]))
+ .fn(async t => {
+ const { isAsync } = t.params;
+ t.doCreateComputePipelineTest(isAsync, false, {
+ layout: 'auto',
+ compute: {
+ module: t.createInvalidShaderModule(),
+ entryPoint: 'main',
+ },
+ });
+ });
+
+g.test('shader_module,compute')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) with valid but different stage shader and matching entryPoint,
+and check that the APIs only accept compute shader.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('shaderModuleStage', ['compute', 'vertex', 'fragment'])
+ )
+ .fn(async t => {
+ const { isAsync, shaderModuleStage } = t.params;
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.getShaderModule(shaderModuleStage, 'main'),
+ entryPoint: 'main',
+ },
+ };
+ t.doCreateComputePipelineTest(isAsync, shaderModuleStage === 'compute', descriptor);
+ });
+
+g.test('shader_module,device_mismatch')
+ .desc(
+ 'Tests createComputePipeline(Async) cannot be called with a shader module created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { isAsync, mismatched } = t.params;
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const module = sourceDevice.createShaderModule({
+ code: '@compute @workgroup_size(1) fn main() {}',
+ });
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module,
+ entryPoint: 'main',
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, !mismatched, descriptor);
+ });
+
+g.test('pipeline_layout,device_mismatch')
+ .desc(
+ 'Tests createComputePipeline(Async) cannot be called with a pipeline layout created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { isAsync, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const layout = sourceDevice.createPipelineLayout({ bindGroupLayouts: [] });
+
+ const descriptor = {
+ layout,
+ compute: {
+ module: t.getShaderModule('compute', 'main'),
+ entryPoint: 'main',
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, !mismatched, descriptor);
+ });
+
+g.test('limits,workgroup_storage_size')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for compute using <= device.limits.maxComputeWorkgroupStorageSize bytes of workgroup storage.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { type: 'vec4<f32>', _typeSize: 16 },
+ { type: 'mat4x4<f32>', _typeSize: 64 },
+ ])
+ .beginSubcases()
+ .combine('countDeltaFromLimit', [0, 1])
+ )
+ .fn(async t => {
+ const { isAsync, type, _typeSize, countDeltaFromLimit } = t.params;
+ const countAtLimit = Math.floor(t.device.limits.maxComputeWorkgroupStorageSize / _typeSize);
+ const count = countAtLimit + countDeltaFromLimit;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ var<workgroup> data: array<${type}, ${count}>;
+ @compute @workgroup_size(64) fn main () {
+ _ = data;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ };
+ t.doCreateComputePipelineTest(isAsync, count <= countAtLimit, descriptor);
+ });
+
+g.test('limits,invocations_per_workgroup')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for compute using <= device.limits.maxComputeInvocationsPerWorkgroup per workgroup.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('size', [
+ // Assume maxComputeWorkgroupSizeX/Y >= 129, maxComputeWorkgroupSizeZ >= 33
+ [128, 1, 2],
+ [129, 1, 2],
+ [2, 128, 1],
+ [2, 129, 1],
+ [1, 8, 32],
+ [1, 8, 33],
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, size } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ @compute @workgroup_size(${size.join(',')}) fn main () {
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ };
+
+ t.doCreateComputePipelineTest(
+ isAsync,
+ size[0] * size[1] * size[2] <= t.device.limits.maxComputeInvocationsPerWorkgroup,
+ descriptor
+ );
+ });
+
+g.test('limits,invocations_per_workgroup,each_component')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for compute workgroup_size attribute has each component no more than their limits.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('size', [
+ // Assume maxComputeInvocationsPerWorkgroup >= 256
+ [64],
+ [256, 1, 1],
+ [257, 1, 1],
+ [1, 256, 1],
+ [1, 257, 1],
+ [1, 1, 63],
+ [1, 1, 64],
+ [1, 1, 65],
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, size } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ @compute @workgroup_size(${size.join(',')}) fn main () {
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ };
+
+ size[1] = size[1] ?? 1;
+ size[2] = size[2] ?? 1;
+
+ const _success =
+ size[0] <= t.device.limits.maxComputeWorkgroupSizeX &&
+ size[1] <= t.device.limits.maxComputeWorkgroupSizeY &&
+ size[2] <= t.device.limits.maxComputeWorkgroupSizeZ;
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('overrides,identifier')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for overridable constants identifiers.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { constants: {}, _success: true },
+ { constants: { c0: 0 }, _success: true },
+ { constants: { c0: 0, c1: 1 }, _success: true },
+ { constants: { c9: 0 }, _success: false },
+ { constants: { 1: 0 }, _success: true },
+ { constants: { c3: 0 }, _success: false }, // pipeline constant id is specified for c3
+ { constants: { 2: 0 }, _success: false },
+ { constants: { 1000: 0 }, _success: true },
+ { constants: { 9999: 0 }, _success: false },
+ { constants: { 1000: 0, c2: 0 }, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ override c0: bool = true; // type: bool
+ override c1: u32 = 0u; // default override
+ @id(1000) override c2: u32 = 10u; // default
+ @id(1) override c3: u32 = 11u; // default
+ @compute @workgroup_size(1) fn main () {
+ // make sure the overridable constants are not optimized out
+ _ = u32(c0);
+ _ = u32(c1);
+ _ = u32(c2);
+ _ = u32(c3);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('overrides,uninitialized')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for uninitialized overridable constants.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { constants: {}, _success: false },
+ { constants: { c0: 0, c2: 0, c8: 0 }, _success: false }, // c5 is missing
+ { constants: { c0: 0, c2: 0, c5: 0, c8: 0 }, _success: true },
+ { constants: { c0: 0, c2: 0, c5: 0, c8: 0, c1: 0 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ override c0: bool; // type: bool
+ override c1: bool = false; // default override
+ override c2: f32; // type: float32
+ override c3: f32 = 0.0; // default override
+ override c4: f32 = 4.0; // default
+ override c5: i32; // type: int32
+ override c6: i32 = 0; // default override
+ override c7: i32 = 7; // default
+ override c8: u32; // type: uint32
+ override c9: u32 = 0u; // default override
+ @id(1000) override c10: u32 = 10u; // default
+ @compute @workgroup_size(1) fn main () {
+ // make sure the overridable constants are not optimized out
+ _ = u32(c0);
+ _ = u32(c1);
+ _ = u32(c2);
+ _ = u32(c3);
+ _ = u32(c4);
+ _ = u32(c5);
+ _ = u32(c6);
+ _ = u32(c7);
+ _ = u32(c8);
+ _ = u32(c9);
+ _ = u32(c10);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('overrides,value,type_error')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for constant values like inf, NaN will results in TypeError.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { constants: { cf: 1 }, _success: true }, // control
+ { constants: { cf: NaN }, _success: false },
+ { constants: { cf: Number.POSITIVE_INFINITY }, _success: false },
+ { constants: { cf: Number.NEGATIVE_INFINITY }, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ override cf: f32 = 0.0;
+ @compute @workgroup_size(1) fn main () {
+ _ = cf;
+ }`,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor, 'TypeError');
+ });
+
+g.test('overrides,value,validation_error')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for unrepresentable constant values in compute stage.
+
+TODO(#2060): test with last_f64_castable.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { constants: { cu: kValue.u32.min }, _success: true },
+ { constants: { cu: kValue.u32.min - 1 }, _success: false },
+ { constants: { cu: kValue.u32.max }, _success: true },
+ { constants: { cu: kValue.u32.max + 1 }, _success: false },
+ { constants: { ci: kValue.i32.negative.min }, _success: true },
+ { constants: { ci: kValue.i32.negative.min - 1 }, _success: false },
+ { constants: { ci: kValue.i32.positive.max }, _success: true },
+ { constants: { ci: kValue.i32.positive.max + 1 }, _success: false },
+ { constants: { cf: kValue.f32.negative.min }, _success: true },
+ { constants: { cf: kValue.f32.negative.first_f64_not_castable }, _success: false },
+ { constants: { cf: kValue.f32.positive.max }, _success: true },
+ { constants: { cf: kValue.f32.positive.first_f64_not_castable }, _success: false },
+ // Conversion to boolean can't fail
+ { constants: { cb: Number.MAX_VALUE }, _success: true },
+ { constants: { cb: kValue.i32.negative.min - 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ override cb: bool = false;
+ override cu: u32 = 0u;
+ override ci: i32 = 0;
+ override cf: f32 = 0.0;
+ @compute @workgroup_size(1) fn main () {
+ _ = cb;
+ _ = cu;
+ _ = ci;
+ _ = cf;
+ }`,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('overrides,value,validation_error,f16')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for unrepresentable f16 constant values in compute stage.
+
+TODO(#2060): Tighten the cases around the valid/invalid boundary once we have WGSL spec
+clarity on whether values like f16.positive.last_f64_castable would be valid. See issue.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { constants: { cf16: kValue.f16.negative.min }, _success: true },
+ { constants: { cf16: kValue.f16.negative.first_f64_not_castable }, _success: false },
+ { constants: { cf16: kValue.f16.positive.max }, _success: true },
+ { constants: { cf16: kValue.f16.positive.first_f64_not_castable }, _success: false },
+ { constants: { cf16: kValue.f32.negative.min }, _success: false },
+ { constants: { cf16: kValue.f32.positive.max }, _success: false },
+ { constants: { cf16: kValue.f32.negative.first_f64_not_castable }, _success: false },
+ { constants: { cf16: kValue.f32.positive.first_f64_not_castable }, _success: false },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
+ })
+ .fn(async t => {
+ const { isAsync, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ enable f16;
+
+ override cf16: f16 = 0.0h;
+ @compute @workgroup_size(1) fn main () {
+ _ = cf16;
+ }`,
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+const kOverridesWorkgroupSizeShaders = {
+ u32: `
+override x: u32 = 1u;
+override y: u32 = 1u;
+override z: u32 = 1u;
+@compute @workgroup_size(x, y, z) fn main () {
+ _ = 0u;
+}
+`,
+ i32: `
+override x: i32 = 1;
+override y: i32 = 1;
+override z: i32 = 1;
+@compute @workgroup_size(x, y, z) fn main () {
+ _ = 0u;
+}
+`,
+};
+
+g.test('overrides,workgroup_size')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for overridable constants used for workgroup size.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('type', ['u32', 'i32'])
+ .combineWithParams([
+ { constants: {}, _success: true },
+ { constants: { x: 0, y: 0, z: 0 }, _success: false },
+ { constants: { x: 1, y: -1, z: 1 }, _success: false },
+ { constants: { x: 1, y: 0, z: 0 }, _success: false },
+ { constants: { x: 16, y: 1, z: 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, type, constants, _success } = t.params;
+
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: kOverridesWorkgroupSizeShaders[type],
+ }),
+ entryPoint: 'main',
+ constants,
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('overrides,workgroup_size,limits')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for overridable constants for workgroupSize exceeds device limits.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combine('type', ['u32', 'i32'])
+ )
+ .fn(async t => {
+ const { isAsync, type } = t.params;
+
+ const limits = t.device.limits;
+
+ const testFn = (x, y, z, _success) => {
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: kOverridesWorkgroupSizeShaders[type],
+ }),
+ entryPoint: 'main',
+ constants: {
+ x,
+ y,
+ z,
+ },
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ };
+
+ testFn(limits.maxComputeWorkgroupSizeX, 1, 1, true);
+ testFn(limits.maxComputeWorkgroupSizeX + 1, 1, 1, false);
+ testFn(1, limits.maxComputeWorkgroupSizeY, 1, true);
+ testFn(1, limits.maxComputeWorkgroupSizeY + 1, 1, false);
+ testFn(1, 1, limits.maxComputeWorkgroupSizeZ, true);
+ testFn(1, 1, limits.maxComputeWorkgroupSizeZ + 1, false);
+ testFn(
+ limits.maxComputeWorkgroupSizeX,
+ limits.maxComputeWorkgroupSizeY,
+ limits.maxComputeWorkgroupSizeZ,
+ limits.maxComputeWorkgroupSizeX *
+ limits.maxComputeWorkgroupSizeY *
+ limits.maxComputeWorkgroupSizeZ <=
+ limits.maxComputeInvocationsPerWorkgroup
+ );
+ });
+
+g.test('overrides,workgroup_size,limits,workgroup_storage_size')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) validation for overridable constants for workgroupStorageSize exceeds device limits.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ )
+ .fn(async t => {
+ const { isAsync } = t.params;
+
+ const limits = t.device.limits;
+
+ const kVec4Size = 16;
+ const maxVec4Count = limits.maxComputeWorkgroupStorageSize / kVec4Size;
+ const kMat4Size = 64;
+ const maxMat4Count = limits.maxComputeWorkgroupStorageSize / kMat4Size;
+
+ const testFn = (vec4Count, mat4Count, _success) => {
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ override a: u32;
+ override b: u32;
+ ${vec4Count <= 0 ? '' : 'var<workgroup> vec4_data: array<vec4<f32>, a>;'}
+ ${mat4Count <= 0 ? '' : 'var<workgroup> mat4_data: array<mat4x4<f32>, b>;'}
+ @compute @workgroup_size(1) fn main() {
+ ${vec4Count <= 0 ? '' : '_ = vec4_data[0];'}
+ ${mat4Count <= 0 ? '' : '_ = mat4_data[0];'}
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: {
+ a: vec4Count,
+ b: mat4Count,
+ },
+ },
+ };
+
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ };
+
+ testFn(1, 1, true);
+ testFn(maxVec4Count + 1, 0, false);
+ testFn(0, maxMat4Count + 1, false);
+ });
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
new file mode 100644
index 0000000000..7d40298935
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroup.spec.js
@@ -0,0 +1,1135 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+ createBindGroup validation tests.
+
+ TODO: Ensure sure tests cover all createBindGroup validation rules.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../common/util/util.js';
+import {
+ allBindingEntries,
+ bindingTypeInfo,
+ bufferBindingEntries,
+ bufferBindingTypeInfo,
+ kAllTextureFormats,
+ kBindableResources,
+ kBufferBindingTypes,
+ kBufferUsages,
+ kCompareFunctions,
+ kLimitInfo,
+ kSamplerBindingTypes,
+ kTextureFormatInfo,
+ kTextureUsages,
+ kTextureViewDimensions,
+ sampledAndStorageBindingEntries,
+ texBindingTypeInfo,
+} from '../../capability_info.js';
+import { GPUConst } from '../../constants.js';
+import { kResourceStates } from '../../gpu_test.js';
+import { getTextureDimensionFromView } from '../../util/texture/base.js';
+
+import { ValidationTest } from './validation_test.js';
+
+function clone(descriptor) {
+ return JSON.parse(JSON.stringify(descriptor));
+}
+
+export const g = makeTestGroup(ValidationTest);
+
+const kStorageTextureFormats = kAllTextureFormats.filter(f => kTextureFormatInfo[f].storage);
+
+g.test('binding_count_mismatch')
+ .desc('Test that the number of entries must match the number of entries in the BindGroupLayout.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('layoutEntryCount', [1, 2, 3])
+ .combine('bindGroupEntryCount', [1, 2, 3])
+ )
+ .fn(async t => {
+ const { layoutEntryCount, bindGroupEntryCount } = t.params;
+
+ const layoutEntries = [];
+ for (let i = 0; i < layoutEntryCount; ++i) {
+ layoutEntries.push({
+ binding: i,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type: 'storage' },
+ });
+ }
+ const bindGroupLayout = t.device.createBindGroupLayout({ entries: layoutEntries });
+
+ const entries = [];
+ for (let i = 0; i < bindGroupEntryCount; ++i) {
+ entries.push({
+ binding: i,
+ resource: { buffer: t.getStorageBuffer() },
+ });
+ }
+
+ const shouldError = layoutEntryCount !== bindGroupEntryCount;
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries,
+ layout: bindGroupLayout,
+ });
+ }, shouldError);
+ });
+
+g.test('binding_must_be_present_in_layout')
+ .desc(
+ 'Test that the binding slot for each entry matches a binding slot defined in the BindGroupLayout.'
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('layoutBinding', [0, 1, 2])
+ .combine('binding', [0, 1, 2])
+ )
+ .fn(async t => {
+ const { layoutBinding, binding } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ { binding: layoutBinding, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ ],
+ });
+
+ const descriptor = {
+ entries: [{ binding, resource: { buffer: t.getStorageBuffer() } }],
+ layout: bindGroupLayout,
+ };
+
+ const shouldError = layoutBinding !== binding;
+ t.expectValidationError(() => {
+ t.device.createBindGroup(descriptor);
+ }, shouldError);
+ });
+
+g.test('binding_must_contain_resource_defined_in_layout')
+ .desc(
+ 'Test that only compatible resource types specified in the BindGroupLayout are allowed for each entry.'
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('resourceType', kBindableResources)
+ .combine('entry', allBindingEntries(false))
+ )
+ .fn(t => {
+ const { resourceType, entry } = t.params;
+ const info = bindingTypeInfo(entry);
+
+ const layout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, ...entry }],
+ });
+
+ const resource = t.getBindingResource(resourceType);
+
+ let resourceBindingIsCompatible;
+ switch (info.resource) {
+ // Either type of sampler may be bound to a filtering sampler binding.
+ case 'filtSamp':
+ resourceBindingIsCompatible = resourceType === 'filtSamp' || resourceType === 'nonFiltSamp';
+ break;
+ // But only non-filtering samplers can be used with non-filtering sampler bindings.
+ case 'nonFiltSamp':
+ resourceBindingIsCompatible = resourceType === 'nonFiltSamp';
+ break;
+ default:
+ resourceBindingIsCompatible = info.resource === resourceType;
+ break;
+ }
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({ layout, entries: [{ binding: 0, resource }] });
+ }, !resourceBindingIsCompatible);
+ });
+
+g.test('texture_binding_must_have_correct_usage')
+ .desc('Tests that texture bindings must have the correct usage.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('entry', sampledAndStorageBindingEntries(false))
+ .combine('usage', kTextureUsages)
+ .unless(({ entry, usage }) => {
+ const info = texBindingTypeInfo(entry);
+ // Can't create the texture for this (usage=STORAGE_BINDING and sampleCount=4), so skip.
+ return usage === GPUConst.TextureUsage.STORAGE_BINDING && info.resource === 'sampledTexMS';
+ })
+ )
+ .fn(async t => {
+ const { entry, usage } = t.params;
+ const info = texBindingTypeInfo(entry);
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, ...entry }],
+ });
+
+ // The `RENDER_ATTACHMENT` usage must be specified if sampleCount > 1 according to WebGPU SPEC.
+ const appliedUsage =
+ info.resource === 'sampledTexMS' ? usage | GPUConst.TextureUsage.RENDER_ATTACHMENT : usage;
+
+ const descriptor = {
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: appliedUsage,
+ sampleCount: info.resource === 'sampledTexMS' ? 4 : 1,
+ };
+ const resource = t.device.createTexture(descriptor).createView();
+
+ const shouldError = (usage & info.usage) === 0;
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource }],
+ layout: bindGroupLayout,
+ });
+ }, shouldError);
+ });
+
+g.test('texture_must_have_correct_component_type')
+ .desc(
+ `
+ Tests that texture bindings must have a format that matches the sample type specified in the BindGroupLayout.
+ - Tests a compatible format for every sample type
+ - Tests an incompatible format for every sample type`
+ )
+ .params(u => u.combine('sampleType', ['float', 'sint', 'uint']))
+ .fn(async t => {
+ const { sampleType } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ texture: { sampleType },
+ },
+ ],
+ });
+
+ let format;
+ if (sampleType === 'float') {
+ format = 'r8unorm';
+ } else if (sampleType === 'sint') {
+ format = 'r8sint';
+ } else if (sampleType === 'uint') {
+ format = 'r8uint';
+ } else {
+ unreachable('Unexpected texture component type');
+ }
+
+ const goodDescriptor = {
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ // Control case
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: t.device.createTexture(goodDescriptor).createView(),
+ },
+ ],
+
+ layout: bindGroupLayout,
+ });
+
+ function* mismatchedTextureFormats() {
+ if (sampleType !== 'float') {
+ yield 'r8unorm';
+ }
+ if (sampleType !== 'sint') {
+ yield 'r8sint';
+ }
+ if (sampleType !== 'uint') {
+ yield 'r8uint';
+ }
+ }
+
+ // Mismatched texture binding formats are not valid.
+ for (const mismatchedTextureFormat of mismatchedTextureFormats()) {
+ const badDescriptor = clone(goodDescriptor);
+ badDescriptor.format = mismatchedTextureFormat;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: t.device.createTexture(badDescriptor).createView() }],
+ layout: bindGroupLayout,
+ });
+ });
+ }
+ });
+
+g.test('texture_must_have_correct_dimension')
+ .desc(
+ `
+ Test that bound texture views match the dimensions supplied in the BindGroupLayout
+ - Test for every GPUTextureViewDimension
+ - Test for both TEXTURE_BINDING and STORAGE_BINDING.
+ `
+ )
+ .params(u =>
+ u
+ .combine('usage', [
+ GPUConst.TextureUsage.TEXTURE_BINDING,
+ GPUConst.TextureUsage.STORAGE_BINDING,
+ ])
+ .combine('viewDimension', kTextureViewDimensions)
+ .unless(
+ p =>
+ p.usage === GPUConst.TextureUsage.STORAGE_BINDING &&
+ (p.viewDimension === 'cube' || p.viewDimension === 'cube-array')
+ )
+ .beginSubcases()
+ .combine('dimension', kTextureViewDimensions)
+ )
+ .fn(async t => {
+ const { usage, viewDimension, dimension } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ usage === GPUTextureUsage.TEXTURE_BINDING
+ ? {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ texture: { viewDimension },
+ }
+ : {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ storageTexture: { access: 'write-only', format: 'rgba8unorm', viewDimension },
+ },
+ ],
+ });
+
+ let height = 16;
+ let depthOrArrayLayers = 6;
+ if (dimension === '1d') {
+ height = 1;
+ depthOrArrayLayers = 1;
+ }
+
+ const texture = t.device.createTexture({
+ size: { width: 16, height, depthOrArrayLayers },
+ format: 'rgba8unorm',
+ usage,
+ dimension: getTextureDimensionFromView(dimension),
+ });
+
+ const shouldError = viewDimension !== dimension;
+ const textureView = texture.createView({ dimension });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: textureView }],
+ layout: bindGroupLayout,
+ });
+ }, shouldError);
+ });
+
+g.test('multisampled_validation')
+ .desc(
+ `
+ Test that the sample count of the texture is greater than 1 if the BindGroup entry's
+ multisampled is true. Otherwise, the texture's sampleCount should be 1.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('multisampled', [true, false])
+ .beginSubcases()
+ .combine('sampleCount', [1, 4])
+ )
+ .fn(async t => {
+ const { multisampled, sampleCount } = t.params;
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ texture: { multisampled },
+ },
+ ],
+ });
+
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount,
+ });
+
+ const isValid = (!multisampled && sampleCount === 1) || (multisampled && sampleCount > 1);
+
+ const textureView = texture.createView();
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: textureView }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('buffer_offset_and_size_for_bind_groups_match')
+ .desc(
+ `
+ Test that a buffer binding's [offset, offset + size) must be contained in the BindGroup entry's buffer.
+ - Test for various offsets and sizes`
+ )
+ .paramsSubcasesOnly([
+ { offset: 0, size: 512, _success: true }, // offset 0 is valid
+ { offset: 256, size: 256, _success: true }, // offset 256 (aligned) is valid
+
+ // Touching the end of the buffer
+ { offset: 0, size: 1024, _success: true },
+ { offset: 0, size: undefined, _success: true },
+ { offset: 256 * 3, size: 256, _success: true },
+ { offset: 256 * 3, size: undefined, _success: true },
+
+ // Zero-sized bindings
+ { offset: 0, size: 0, _success: false },
+ { offset: 256, size: 0, _success: false },
+ { offset: 1024, size: 0, _success: false },
+ { offset: 1024, size: undefined, _success: false },
+
+ // Unaligned buffer offset is invalid
+ { offset: 1, size: 256, _success: false },
+ { offset: 1, size: undefined, _success: false },
+ { offset: 128, size: 256, _success: false },
+ { offset: 255, size: 256, _success: false },
+
+ // Out-of-bounds
+ { offset: 256 * 5, size: 0, _success: false }, // offset is OOB
+ { offset: 0, size: 256 * 5, _success: false }, // size is OOB
+ { offset: 1024, size: 1, _success: false }, // offset+size is OOB
+ ])
+ .fn(async t => {
+ const { offset, size, _success } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }],
+ });
+
+ const buffer = t.device.createBuffer({
+ size: 1024,
+ usage: GPUBufferUsage.STORAGE,
+ });
+
+ const descriptor = {
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer, offset, size },
+ },
+ ],
+
+ layout: bindGroupLayout,
+ };
+
+ if (_success) {
+ // Control case
+ t.device.createBindGroup(descriptor);
+ } else {
+ // Buffer offset and/or size don't match in bind groups.
+ t.expectValidationError(() => {
+ t.device.createBindGroup(descriptor);
+ });
+ }
+ });
+
+g.test('minBindingSize')
+ .desc('Tests that minBindingSize is correctly enforced.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('minBindingSize', [undefined, 4, 8, 256])
+ .expand('size', ({ minBindingSize }) =>
+ minBindingSize !== undefined
+ ? [minBindingSize - 4, minBindingSize, minBindingSize + 4]
+ : [4, 256]
+ )
+ )
+ .fn(t => {
+ const { size, minBindingSize } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ buffer: {
+ type: 'storage',
+ minBindingSize,
+ },
+ },
+ ],
+ });
+
+ const storageBuffer = t.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.STORAGE,
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: storageBuffer,
+ },
+ },
+ ],
+ });
+ }, minBindingSize !== undefined && size < minBindingSize);
+ });
+
+g.test('buffer,resource_state')
+ .desc('Test bind group creation with various buffer resource states')
+ .paramsSubcasesOnly(u =>
+ u.combine('state', kResourceStates).combine('entry', bufferBindingEntries(true))
+ )
+ .fn(t => {
+ const { state, entry } = t.params;
+
+ assert(entry.buffer !== undefined);
+ const info = bufferBindingTypeInfo(entry.buffer);
+
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ {
+ ...entry,
+ binding: 0,
+ visibility: info.validStages,
+ },
+ ],
+ });
+
+ const buffer = t.createBufferWithState(state, {
+ usage: info.usage,
+ size: 4,
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer,
+ },
+ },
+ ],
+ });
+ }, state === 'invalid');
+ });
+
+g.test('texture,resource_state')
+ .desc('Test bind group creation with various texture resource states')
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('state', kResourceStates)
+ .combine('entry', sampledAndStorageBindingEntries(true, 'rgba8unorm'))
+ )
+ .fn(t => {
+ const { state, entry } = t.params;
+ const info = texBindingTypeInfo(entry);
+
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ {
+ ...entry,
+ binding: 0,
+ visibility: info.validStages,
+ },
+ ],
+ });
+
+ // The `RENDER_ATTACHMENT` usage must be specified if sampleCount > 1 according to WebGPU SPEC.
+ const usage = entry.texture?.multisampled
+ ? info.usage | GPUConst.TextureUsage.RENDER_ATTACHMENT
+ : info.usage;
+ const texture = t.createTextureWithState(state, {
+ usage,
+ size: [1, 1],
+ format: 'rgba8unorm',
+ sampleCount: entry.texture?.multisampled ? 4 : 1,
+ });
+
+ let textureView;
+ t.expectValidationError(() => {
+ textureView = texture.createView();
+ }, state === 'invalid');
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: textureView,
+ },
+ ],
+ });
+ }, state === 'invalid');
+ });
+
+g.test('bind_group_layout,device_mismatch')
+ .desc(
+ 'Tests createBindGroup cannot be called with a bind group layout created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const mismatched = t.params.mismatched;
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const bgl = sourceDevice.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUConst.ShaderStage.VERTEX,
+ buffer: {},
+ },
+ ],
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: t.getUniformBuffer() },
+ },
+ ],
+ });
+ }, mismatched);
+ });
+
+g.test('binding_resources,device_mismatch')
+ .desc(
+ `
+ Tests createBindGroup cannot be called with various resources created from another device
+ Test with two resources to make sure all resources can be validated:
+ - resource0 and resource1 from same device
+ - resource0 and resource1 from different device
+
+ TODO: test GPUExternalTexture as a resource
+ `
+ )
+ .params(u =>
+ u
+ .combine('entry', [
+ { buffer: { type: 'storage' } },
+ { sampler: { type: 'filtering' } },
+ { texture: { multisampled: false } },
+ { storageTexture: { access: 'write-only', format: 'rgba8unorm' } },
+ ])
+ .beginSubcases()
+ .combineWithParams([
+ { resource0Mismatched: false, resource1Mismatched: false }, //control case
+ { resource0Mismatched: true, resource1Mismatched: false },
+ { resource0Mismatched: false, resource1Mismatched: true },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { entry, resource0Mismatched, resource1Mismatched } = t.params;
+
+ const info = bindingTypeInfo(entry);
+
+ const resource0 = resource0Mismatched
+ ? t.getDeviceMismatchedBindingResource(info.resource)
+ : t.getBindingResource(info.resource);
+ const resource1 = resource1Mismatched
+ ? t.getDeviceMismatchedBindingResource(info.resource)
+ : t.getBindingResource(info.resource);
+
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: info.validStages,
+ ...entry,
+ },
+ {
+ binding: 1,
+ visibility: info.validStages,
+ ...entry,
+ },
+ ],
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: resource0,
+ },
+ {
+ binding: 1,
+ resource: resource1,
+ },
+ ],
+ });
+ }, resource0Mismatched || resource1Mismatched);
+ });
+
+g.test('storage_texture,usage')
+ .desc(
+ `
+ Test that the texture usage contains STORAGE_BINDING if the BindGroup entry defines
+ storageTexture.
+ `
+ )
+ .params(u =>
+ 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)
+ )
+ .fn(async t => {
+ const { usage0, usage1 } = t.params;
+
+ const usage = usage0 | usage1;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ storageTexture: { access: 'write-only', format: 'rgba8unorm' },
+ },
+ ],
+ });
+
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage,
+ });
+
+ const isValid = GPUTextureUsage.STORAGE_BINDING & usage;
+
+ const textureView = texture.createView();
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: textureView }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('storage_texture,mip_level_count')
+ .desc(
+ `
+ Test that the mip level count of the resource of the BindGroup entry as a descriptor is 1 if the
+ BindGroup entry defines storageTexture. If the mip level count is not 1, a validation error
+ should be generated.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('baseMipLevel', [1, 2])
+ .combine('mipLevelCount', [1, 2])
+ )
+ .fn(async t => {
+ const { baseMipLevel, mipLevelCount } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ storageTexture: { access: 'write-only', format: 'rgba8unorm' },
+ },
+ ],
+ });
+
+ const MIP_LEVEL_COUNT = 4;
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.STORAGE_BINDING,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ });
+
+ const textureView = texture.createView({ baseMipLevel, mipLevelCount });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: textureView }],
+ layout: bindGroupLayout,
+ });
+ }, mipLevelCount !== 1);
+ });
+
+g.test('storage_texture,format')
+ .desc(
+ `
+ Test that the format of the storage texture is equal to resource's descriptor format if the
+ BindGroup entry defines storageTexture.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('storageTextureFormat', kStorageTextureFormats)
+ .combine('resourceFormat', kStorageTextureFormats)
+ )
+ .fn(async t => {
+ const { storageTextureFormat, resourceFormat } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ storageTexture: { access: 'write-only', format: storageTextureFormat },
+ },
+ ],
+ });
+
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: resourceFormat,
+ usage: GPUTextureUsage.STORAGE_BINDING,
+ });
+
+ const isValid = storageTextureFormat === resourceFormat;
+ const textureView = texture.createView({ format: resourceFormat });
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: textureView }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('buffer,usage')
+ .desc(
+ `
+ Test that the buffer usage contains 'UNIFORM' if the BindGroup entry defines buffer and it's
+ type is 'uniform', and the buffer usage contains 'STORAGE' if the BindGroup entry's buffer type
+ is 'storage'|read-only-storage'.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('type', kBufferBindingTypes)
+ // If usage0 and usage1 are the same, the usage being test is a single usage. Otherwise, it's
+ // a combined usage.
+ .beginSubcases()
+ .combine('usage0', kBufferUsages)
+ .combine('usage1', kBufferUsages)
+ .unless(
+ ({ usage0, usage1 }) =>
+ ((usage0 | usage1) & (GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.MAP_WRITE)) !==
+ 0
+ )
+ )
+ .fn(async t => {
+ const { type, usage0, usage1 } = t.params;
+
+ const usage = usage0 | usage1;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type },
+ },
+ ],
+ });
+
+ const buffer = t.device.createBuffer({
+ size: 4,
+ usage,
+ });
+
+ let isValid = false;
+ if (type === 'uniform') {
+ isValid = GPUBufferUsage.UNIFORM & usage ? true : false;
+ } else if (type === 'storage' || type === 'read-only-storage') {
+ isValid = GPUBufferUsage.STORAGE & usage ? true : false;
+ }
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer } }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('buffer,resource_offset')
+ .desc(
+ `
+ Test that the resource.offset of the BindGroup entry is a multiple of limits.
+ 'minUniformBufferOffsetAlignment|minStorageBufferOffsetAlignment' if the BindGroup entry defines
+ buffer and the buffer type is 'uniform|storage|read-only-storage'.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('type', kBufferBindingTypes)
+ .beginSubcases()
+ .expand('offset', ({ type }) =>
+ type === 'uniform'
+ ? [
+ kLimitInfo.minUniformBufferOffsetAlignment.default,
+ kLimitInfo.minUniformBufferOffsetAlignment.default * 0.5,
+ kLimitInfo.minUniformBufferOffsetAlignment.default * 1.5,
+ kLimitInfo.minUniformBufferOffsetAlignment.default + 2,
+ ]
+ : [
+ kLimitInfo.minStorageBufferOffsetAlignment.default,
+ kLimitInfo.minStorageBufferOffsetAlignment.default * 0.5,
+ kLimitInfo.minStorageBufferOffsetAlignment.default * 1.5,
+ kLimitInfo.minStorageBufferOffsetAlignment.default + 2,
+ ]
+ )
+ )
+ .fn(async t => {
+ const { type, offset } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type },
+ },
+ ],
+ });
+
+ let usage, isValid;
+ if (type === 'uniform') {
+ usage = GPUBufferUsage.UNIFORM;
+ isValid = offset % kLimitInfo.minUniformBufferOffsetAlignment.default === 0;
+ } else {
+ usage = GPUBufferUsage.STORAGE;
+ isValid = offset % kLimitInfo.minStorageBufferOffsetAlignment.default === 0;
+ }
+
+ const buffer = t.device.createBuffer({
+ size: 1024,
+ usage,
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer, offset } }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('buffer,resource_binding_size')
+ .desc(
+ `
+ Test that the buffer binding size of the BindGroup entry is equal to or less than limits.
+ 'maxUniformBufferBindingSize|maxStorageBufferBindingSize' if the BindGroup entry defines
+ buffer and the buffer type is 'uniform|storage|read-only-storage'.
+ `
+ )
+ .params(u =>
+ u
+ .combine('type', kBufferBindingTypes)
+ .beginSubcases()
+ // Test a size of 1 (for uniform buffer) or 4 (for storage and read-only storage buffer)
+ // then values just within and just above the limit.
+ .expand('bindingSize', ({ type }) =>
+ type === 'uniform'
+ ? [
+ 1,
+ kLimitInfo.maxUniformBufferBindingSize.default,
+ kLimitInfo.maxUniformBufferBindingSize.default + 1,
+ ]
+ : [
+ 4,
+ kLimitInfo.maxStorageBufferBindingSize.default,
+ kLimitInfo.maxStorageBufferBindingSize.default + 4,
+ ]
+ )
+ )
+ .fn(async t => {
+ const { type, bindingSize } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type },
+ },
+ ],
+ });
+
+ let usage, isValid;
+ if (type === 'uniform') {
+ usage = GPUBufferUsage.UNIFORM;
+ isValid = bindingSize <= kLimitInfo.maxUniformBufferBindingSize.default;
+ } else {
+ usage = GPUBufferUsage.STORAGE;
+ isValid = bindingSize <= kLimitInfo.maxStorageBufferBindingSize.default;
+ }
+
+ const buffer = t.device.createBuffer({
+ size: kLimitInfo.maxStorageBufferBindingSize.default,
+ usage,
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer, size: bindingSize } }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('buffer,effective_buffer_binding_size')
+ .desc(
+ `
+ Test that the effective buffer binding size of the BindGroup entry must be a multiple of 4 if the
+ buffer type is 'storage|read-only-storage', while there is no such restriction on uniform buffers.
+`
+ )
+ .params(u =>
+ u
+ .combine('type', kBufferBindingTypes)
+ .beginSubcases()
+ .expand('offset', ({ type }) =>
+ type === 'uniform'
+ ? [0, kLimitInfo.minUniformBufferOffsetAlignment.default]
+ : [0, kLimitInfo.minStorageBufferOffsetAlignment.default]
+ )
+ .expand('bufferSize', ({ type }) =>
+ type === 'uniform'
+ ? [
+ kLimitInfo.minUniformBufferOffsetAlignment.default + 8,
+ kLimitInfo.minUniformBufferOffsetAlignment.default + 10,
+ ]
+ : [
+ kLimitInfo.minStorageBufferOffsetAlignment.default + 8,
+ kLimitInfo.minStorageBufferOffsetAlignment.default + 10,
+ ]
+ )
+ .combine('bindingSize', [undefined, 2, 4, 6])
+ )
+ .fn(async t => {
+ const { type, offset, bufferSize, bindingSize } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type },
+ },
+ ],
+ });
+
+ const effectiveBindingSize = bindingSize ?? bufferSize - offset;
+ let usage, isValid;
+ if (type === 'uniform') {
+ usage = GPUBufferUsage.UNIFORM;
+ isValid = true;
+ } else {
+ usage = GPUBufferUsage.STORAGE;
+ isValid = effectiveBindingSize % 4 === 0;
+ }
+
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage,
+ });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer, offset, size: bindingSize } }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
+
+g.test('sampler,device_mismatch')
+ .desc(`Tests createBindGroup cannot be called with a sampler created from another device.`)
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ sampler: { type: 'filtering' },
+ },
+ ],
+ });
+
+ const sampler = sourceDevice.createSampler();
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: sampler }],
+ layout: bindGroupLayout,
+ });
+ }, mismatched);
+ });
+
+g.test('sampler,compare_function_with_binding_type')
+ .desc(
+ `
+ Test that the sampler of the BindGroup has a 'compareFunction' value if the sampler type of the
+ BindGroupLayout is 'comparison'. Other sampler types should not have 'compare' field in
+ the descriptor of the sampler.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('bgType', kSamplerBindingTypes)
+ .beginSubcases()
+ .combine('compareFunction', [undefined, ...kCompareFunctions])
+ )
+ .fn(async t => {
+ const { bgType, compareFunction } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ sampler: { type: bgType },
+ },
+ ],
+ });
+
+ const isValid =
+ bgType === 'comparison' ? compareFunction !== undefined : compareFunction === undefined;
+
+ const sampler = t.device.createSampler({ compare: compareFunction });
+
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: sampler }],
+ layout: bindGroupLayout,
+ });
+ }, !isValid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js
new file mode 100644
index 0000000000..89bb2e31c7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js
@@ -0,0 +1,456 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+createBindGroupLayout validation tests.
+
+TODO: make sure tests are complete.
+`;
+import { kUnitCaseParamsBuilder } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import {
+ kAllTextureFormats,
+ kShaderStages,
+ kShaderStageCombinations,
+ kStorageTextureAccessValues,
+ kTextureFormatInfo,
+ kTextureSampleTypes,
+ kTextureViewDimensions,
+ allBindingEntries,
+ bindingTypeInfo,
+ bufferBindingTypeInfo,
+ kBufferBindingTypes,
+} from '../../capability_info.js';
+
+import { ValidationTest } from './validation_test.js';
+
+function clone(descriptor) {
+ return JSON.parse(JSON.stringify(descriptor));
+}
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('duplicate_bindings')
+ .desc('Test that uniqueness of binding numbers across entries is enforced.')
+ .paramsSubcasesOnly([
+ { bindings: [0, 1], _valid: true },
+ { bindings: [0, 0], _valid: false },
+ ])
+ .fn(async t => {
+ const { bindings, _valid } = t.params;
+ const entries = [];
+
+ for (const binding of bindings) {
+ entries.push({
+ binding,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type: 'storage' },
+ });
+ }
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries,
+ });
+ }, !_valid);
+ });
+
+// MAINTENANCE_TODO: Move this into kLimits with the proper name after the spec PR lands.
+// https://github.com/gpuweb/gpuweb/pull/3318
+const kMaxBindingsPerBindGroup = 640;
+
+g.test('maximum_binding_limit')
+ .desc(
+ `
+ Test that a validation error is generated if the binding number exceeds the maximum binding limit.
+
+ TODO: Need to also test with higher limits enabled on the device, once we have a way to do that.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('binding', [1, 4, 8, 256, kMaxBindingsPerBindGroup - 1, kMaxBindingsPerBindGroup])
+ )
+ .fn(async t => {
+ const { binding } = t.params;
+ const entries = [];
+
+ entries.push({
+ binding,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type: 'storage' },
+ });
+
+ const success = binding < kMaxBindingsPerBindGroup;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries,
+ });
+ }, !success);
+ });
+
+g.test('visibility')
+ .desc(
+ `
+ Test that only the appropriate combinations of visibilities are allowed for each resource type.
+ - Test each possible combination of shader stage visibilities.
+ - Test each type of bind group resource.`
+ )
+ .params(u =>
+ u
+ .combine('visibility', kShaderStageCombinations)
+ .beginSubcases()
+ .combine('entry', allBindingEntries(false))
+ )
+ .fn(async t => {
+ const { visibility, entry } = t.params;
+ const info = bindingTypeInfo(entry);
+
+ const success = (visibility & ~info.validStages) === 0;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility, ...entry }],
+ });
+ }, !success);
+ });
+
+g.test('visibility,VERTEX_shader_stage_buffer_type')
+ .desc(
+ `
+ Test that a validation error is generated if the buffer type is 'storage' when the
+ visibility of the entry includes VERTEX.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('shaderStage', kShaderStageCombinations)
+ .beginSubcases()
+ .combine('type', kBufferBindingTypes)
+ )
+ .fn(async t => {
+ const { shaderStage, type } = t.params;
+
+ const success = !(type === 'storage' && shaderStage & GPUShaderStage.VERTEX);
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: shaderStage,
+ buffer: { type },
+ },
+ ],
+ });
+ }, !success);
+ });
+
+g.test('visibility,VERTEX_shader_stage_storage_texture_access')
+ .desc(
+ `
+ Test that a validation error is generated if the access value is 'write-only' when the
+ visibility of the entry includes VERTEX.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('shaderStage', kShaderStageCombinations)
+ .beginSubcases()
+ .combine('access', [undefined, ...kStorageTextureAccessValues])
+ )
+ .fn(async t => {
+ const { shaderStage, access } = t.params;
+
+ const success = !(
+ (access ?? 'write-only') === 'write-only' && shaderStage & GPUShaderStage.VERTEX
+ );
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: shaderStage,
+ storageTexture: { access, format: 'rgba8unorm' },
+ },
+ ],
+ });
+ }, !success);
+ });
+
+g.test('multisampled_validation')
+ .desc(
+ `
+ Test that multisampling is only allowed if view dimensions is "2d" and the sampleType is not
+ "float".
+ `
+ )
+ .params(u =>
+ u //
+ .combine('viewDimension', [undefined, ...kTextureViewDimensions])
+ .beginSubcases()
+ .combine('sampleType', [undefined, ...kTextureSampleTypes])
+ )
+ .fn(async t => {
+ const { viewDimension, sampleType } = t.params;
+
+ const success =
+ (viewDimension === '2d' || viewDimension === undefined) &&
+ (sampleType ?? 'float') !== 'float';
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ texture: { multisampled: true, viewDimension, sampleType },
+ },
+ ],
+ });
+ }, !success);
+ });
+
+g.test('max_dynamic_buffers')
+ .desc(
+ `
+ Test that limits on the maximum number of dynamic buffers are enforced.
+ - Test creation of a bind group layout using the maximum number of dynamic buffers works.
+ - Test creation of a bind group layout using the maximum number of dynamic buffers + 1 fails.
+ - TODO(#230): Update to enforce per-stage and per-pipeline-layout limits on BGLs as well.`
+ )
+ .params(u =>
+ u
+ .combine('type', kBufferBindingTypes)
+ .beginSubcases()
+ .combine('extraDynamicBuffers', [0, 1])
+ .combine('staticBuffers', [0, 1])
+ )
+ .fn(async t => {
+ const { type, extraDynamicBuffers, staticBuffers } = t.params;
+ const info = bufferBindingTypeInfo({ type });
+
+ const dynamicBufferCount = info.perPipelineLimitClass.maxDynamic + extraDynamicBuffers;
+
+ const entries = [];
+ for (let i = 0; i < dynamicBufferCount; i++) {
+ entries.push({
+ binding: i,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type, hasDynamicOffset: true },
+ });
+ }
+
+ for (let i = dynamicBufferCount; i < dynamicBufferCount + staticBuffers; i++) {
+ entries.push({
+ binding: i,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type, hasDynamicOffset: false },
+ });
+ }
+
+ const descriptor = {
+ entries,
+ };
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout(descriptor);
+ }, extraDynamicBuffers > 0);
+ });
+
+/**
+ * One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|.
+ * For each item in the array returned here, a case will be generated which tests a pipeline
+ * layout with one extra bind group layout with one extra binding. That extra binding will have:
+ *
+ * - If extraTypeSame, any of the binding types which counts toward the same limit as |type|.
+ * (i.e. 'storage-buffer' <-> 'readonly-storage-buffer').
+ * - Otherwise, an arbitrary other type.
+ */
+function* pickExtraBindingTypesForPerStage(entry, extraTypeSame) {
+ if (extraTypeSame) {
+ const info = bindingTypeInfo(entry);
+ for (const extra of allBindingEntries(false)) {
+ const extraInfo = bindingTypeInfo(extra);
+ if (info.perStageLimitClass.class === extraInfo.perStageLimitClass.class) {
+ yield extra;
+ }
+ }
+ } else {
+ yield entry.sampler ? { texture: {} } : { sampler: {} };
+ }
+}
+
+const kMaxResourcesCases = kUnitCaseParamsBuilder
+ .combine('maxedEntry', allBindingEntries(false))
+ .beginSubcases()
+ .combine('maxedVisibility', kShaderStages)
+ .filter(p => (bindingTypeInfo(p.maxedEntry).validStages & p.maxedVisibility) !== 0)
+ .expand('extraEntry', p => [
+ ...pickExtraBindingTypesForPerStage(p.maxedEntry, true),
+ ...pickExtraBindingTypesForPerStage(p.maxedEntry, false),
+ ])
+ .combine('extraVisibility', kShaderStages)
+ .filter(p => (bindingTypeInfo(p.extraEntry).validStages & p.extraVisibility) !== 0);
+
+// Should never fail unless kMaxBindingsPerBindGroup is exceeded, because the validation for
+// resources-of-type-per-stage is in pipeline layout creation.
+g.test('max_resources_per_stage,in_bind_group_layout')
+ .desc(
+ `
+ Test that the maximum number of bindings of a given type per-stage cannot be exceeded in a
+ single bind group layout.
+ - Test each binding type.
+ - Test that creation of a bind group layout using the maximum number of bindings works.
+ - Test that creation of a bind group layout using the maximum number of bindings + 1 fails.
+ - TODO(#230): Update to enforce per-stage and per-pipeline-layout limits on BGLs as well.`
+ )
+ .params(kMaxResourcesCases)
+ .fn(async t => {
+ const { maxedEntry, extraEntry, maxedVisibility, extraVisibility } = t.params;
+ const maxedTypeInfo = bindingTypeInfo(maxedEntry);
+ const maxedCount = maxedTypeInfo.perStageLimitClass.max;
+ const extraTypeInfo = bindingTypeInfo(extraEntry);
+
+ const maxResourceBindings = [];
+ for (let i = 0; i < maxedCount; i++) {
+ maxResourceBindings.push({
+ binding: i,
+ visibility: maxedVisibility,
+ ...maxedEntry,
+ });
+ }
+
+ const goodDescriptor = { entries: maxResourceBindings };
+
+ // Control
+ t.device.createBindGroupLayout(goodDescriptor);
+
+ // Add an entry counting towards the same limit. It should produce a validation error.
+ const newDescriptor = clone(goodDescriptor);
+ newDescriptor.entries.push({
+ binding: maxedCount,
+ visibility: extraVisibility,
+ ...extraEntry,
+ });
+
+ const newBindingCountsTowardSamePerStageLimit =
+ (maxedVisibility & extraVisibility) !== 0 &&
+ maxedTypeInfo.perStageLimitClass.class === extraTypeInfo.perStageLimitClass.class;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout(newDescriptor);
+ }, newBindingCountsTowardSamePerStageLimit);
+ });
+
+// One pipeline layout can have a maximum number of each type of binding *per stage* (which is
+// different for each type). Test that the max works, then add one more binding of same-or-different
+// type and same-or-different visibility.
+g.test('max_resources_per_stage,in_pipeline_layout')
+ .desc(
+ `
+ Test that the maximum number of bindings of a given type per-stage cannot be exceeded across
+ multiple bind group layouts when creating a pipeline layout.
+ - Test each binding type.
+ - Test that creation of a pipeline using the maximum number of bindings works.
+ - Test that creation of a pipeline using the maximum number of bindings + 1 fails.
+ `
+ )
+ .params(kMaxResourcesCases)
+ .fn(async t => {
+ const { maxedEntry, extraEntry, maxedVisibility, extraVisibility } = t.params;
+ const maxedTypeInfo = bindingTypeInfo(maxedEntry);
+ const maxedCount = maxedTypeInfo.perStageLimitClass.max;
+ const extraTypeInfo = bindingTypeInfo(extraEntry);
+
+ const maxResourceBindings = [];
+ for (let i = 0; i < maxedCount; i++) {
+ maxResourceBindings.push({
+ binding: i,
+ visibility: maxedVisibility,
+ ...maxedEntry,
+ });
+ }
+
+ const goodLayout = t.device.createBindGroupLayout({ entries: maxResourceBindings });
+
+ // Control
+ t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout] });
+
+ const extraLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: extraVisibility,
+ ...extraEntry,
+ },
+ ],
+ });
+
+ // Some binding types use the same limit, e.g. 'storage-buffer' and 'readonly-storage-buffer'.
+ const newBindingCountsTowardSamePerStageLimit =
+ (maxedVisibility & extraVisibility) !== 0 &&
+ maxedTypeInfo.perStageLimitClass.class === extraTypeInfo.perStageLimitClass.class;
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout, extraLayout] });
+ }, newBindingCountsTowardSamePerStageLimit);
+ });
+
+g.test('storage_texture,layout_dimension')
+ .desc(
+ `
+ Test that viewDimension is not cube or cube-array if storageTextureLayout is not undefined.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('viewDimension', [undefined, ...kTextureViewDimensions])
+ )
+ .fn(async t => {
+ const { viewDimension } = t.params;
+
+ const success = viewDimension !== 'cube' && viewDimension !== `cube-array`;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ storageTexture: { format: 'rgba8unorm', viewDimension },
+ },
+ ],
+ });
+ }, !success);
+ });
+
+g.test('storage_texture,formats')
+ .desc(
+ `
+ Test that a validation error is generated if the format doesn't support the storage usage.
+
+ TODO: Test "bgra8unorm" with the "bgra8unorm-storage" feature.
+ `
+ )
+ .params(u => u.combine('format', kAllTextureFormats))
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ storageTexture: { format },
+ },
+ ],
+ });
+ }, !info.storage);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js
new file mode 100644
index 0000000000..6d17845bf0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js
@@ -0,0 +1,157 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+createPipelineLayout validation tests.
+
+TODO: review existing tests, write descriptions, and make sure tests are complete.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { bufferBindingTypeInfo, kBufferBindingTypes } from '../../capability_info.js';
+
+import { ValidationTest } from './validation_test.js';
+
+function clone(descriptor) {
+ return JSON.parse(JSON.stringify(descriptor));
+}
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('number_of_dynamic_buffers_exceeds_the_maximum_value')
+ .desc(
+ `
+ Test that creating a pipeline layout fails with a validation error if the number of dynamic
+ buffers exceeds the maximum value in the pipeline layout.
+ - Test that creation of a pipeline using the maximum number of dynamic buffers added a dynamic
+ buffer fails.
+
+ TODO(#230): Update to enforce per-stage and per-pipeline-layout limits on BGLs as well.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('visibility', [0, 2, 4, 6])
+ .combine('type', kBufferBindingTypes)
+ )
+ .fn(async t => {
+ const { type, visibility } = t.params;
+ const { maxDynamic } = bufferBindingTypeInfo({ type }).perPipelineLimitClass;
+
+ const maxDynamicBufferBindings = [];
+ for (let binding = 0; binding < maxDynamic; binding++) {
+ maxDynamicBufferBindings.push({
+ binding,
+ visibility,
+ buffer: { type, hasDynamicOffset: true },
+ });
+ }
+
+ const maxDynamicBufferBindGroupLayout = t.device.createBindGroupLayout({
+ entries: maxDynamicBufferBindings,
+ });
+
+ const goodDescriptor = {
+ entries: [{ binding: 0, visibility, buffer: { type, hasDynamicOffset: false } }],
+ };
+
+ const goodPipelineLayoutDescriptor = {
+ bindGroupLayouts: [
+ maxDynamicBufferBindGroupLayout,
+ t.device.createBindGroupLayout(goodDescriptor),
+ ],
+ };
+
+ // Control case
+ t.device.createPipelineLayout(goodPipelineLayoutDescriptor);
+
+ // Check dynamic buffers exceed maximum in pipeline layout.
+ const badDescriptor = clone(goodDescriptor);
+ badDescriptor.entries[0].buffer.hasDynamicOffset = true;
+
+ const badPipelineLayoutDescriptor = {
+ bindGroupLayouts: [
+ maxDynamicBufferBindGroupLayout,
+ t.device.createBindGroupLayout(badDescriptor),
+ ],
+ };
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout(badPipelineLayoutDescriptor);
+ });
+ });
+
+g.test('number_of_bind_group_layouts_exceeds_the_maximum_value')
+ .desc(
+ `
+ Test that creating a pipeline layout fails with a validation error if the number of bind group
+ layouts exceeds the maximum value in the pipeline layout.
+ - Test that creation of a pipeline using the maximum number of bind groups added a bind group
+ fails.
+ `
+ )
+ .fn(async t => {
+ const bindGroupLayoutDescriptor = {
+ entries: [],
+ };
+
+ // 4 is the maximum number of bind group layouts.
+ const maxBindGroupLayouts = [1, 2, 3, 4].map(() =>
+ t.device.createBindGroupLayout(bindGroupLayoutDescriptor)
+ );
+
+ const goodPipelineLayoutDescriptor = {
+ bindGroupLayouts: maxBindGroupLayouts,
+ };
+
+ // Control case
+ t.device.createPipelineLayout(goodPipelineLayoutDescriptor);
+
+ // Check bind group layouts exceed maximum in pipeline layout.
+ const badPipelineLayoutDescriptor = {
+ bindGroupLayouts: [
+ ...maxBindGroupLayouts,
+ t.device.createBindGroupLayout(bindGroupLayoutDescriptor),
+ ],
+ };
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout(badPipelineLayoutDescriptor);
+ });
+ });
+
+g.test('bind_group_layouts,device_mismatch')
+ .desc(
+ `
+ Tests createPipelineLayout cannot be called with bind group layouts created from another device
+ Test with two layouts to make sure all layouts can be validated:
+ - layout0 and layout1 from same device
+ - layout0 and layout1 from different device
+ `
+ )
+ .paramsSubcasesOnly([
+ { layout0Mismatched: false, layout1Mismatched: false }, // control case
+ { layout0Mismatched: true, layout1Mismatched: false },
+ { layout0Mismatched: false, layout1Mismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { layout0Mismatched, layout1Mismatched } = t.params;
+
+ const mismatched = layout0Mismatched || layout1Mismatched;
+
+ const bglDescriptor = {
+ entries: [],
+ };
+
+ const layout0 = layout0Mismatched
+ ? t.mismatchedDevice.createBindGroupLayout(bglDescriptor)
+ : t.device.createBindGroupLayout(bglDescriptor);
+ const layout1 = layout1Mismatched
+ ? t.mismatchedDevice.createBindGroupLayout(bglDescriptor)
+ : t.device.createBindGroupLayout(bglDescriptor);
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout({ bindGroupLayouts: [layout0, layout1] });
+ }, mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createSampler.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createSampler.spec.js
new file mode 100644
index 0000000000..df3569e293
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createSampler.spec.js
@@ -0,0 +1,56 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+createSampler validation tests.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+import { ValidationTest } from './validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('lodMinAndMaxClamp')
+ .desc('test different combinations of min and max clamp values')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('lodMinClamp', [-4e-30, -1, 0, 0.5, 1, 10, 4e30])
+ .combine('lodMaxClamp', [-4e-30, -1, 0, 0.5, 1, 10, 4e30])
+ )
+ .fn(async t => {
+ t.expectValidationError(() => {
+ t.device.createSampler({
+ lodMinClamp: t.params.lodMinClamp,
+ lodMaxClamp: t.params.lodMaxClamp,
+ });
+ }, t.params.lodMinClamp > t.params.lodMaxClamp || t.params.lodMinClamp < 0 || t.params.lodMaxClamp < 0);
+ });
+
+g.test('maxAnisotropy')
+ .desc('test different maxAnisotropy values and combinations with min/mag/mipmapFilter')
+ .params(u =>
+ u //
+ .beginSubcases()
+ .combineWithParams([
+ ...u.combine('maxAnisotropy', [-1, undefined, 0, 1, 2, 4, 7, 16, 32, 33, 1024]),
+ { minFilter: 'nearest' },
+ { magFilter: 'nearest' },
+ { mipmapFilter: 'nearest' },
+ ])
+ )
+ .fn(async t => {
+ const {
+ maxAnisotropy = 1,
+ minFilter = 'linear',
+ magFilter = 'linear',
+ mipmapFilter = 'linear',
+ } = t.params;
+
+ t.expectValidationError(() => {
+ t.device.createSampler({
+ minFilter,
+ magFilter,
+ mipmapFilter,
+ maxAnisotropy,
+ });
+ }, maxAnisotropy < 1 || (maxAnisotropy > 1 && !(minFilter === 'linear' && magFilter === 'linear' && mipmapFilter === 'linear')));
+ });
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
new file mode 100644
index 0000000000..4d3abfe1d3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createTexture.spec.js
@@ -0,0 +1,877 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `createTexture validation tests.`;
+import { SkipTestCase } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+import {
+ kTextureFormats,
+ kTextureFormatInfo,
+ kCompressedTextureFormats,
+ kTextureDimensions,
+ kTextureUsages,
+ kUncompressedTextureFormats,
+ kRegularTextureFormats,
+ kFeaturesForFormats,
+ textureDimensionAndFormatCompatible,
+ kLimitInfo,
+ viewCompatible,
+ filterFormatsByFeature,
+} from '../../capability_info.js';
+import { GPUConst } from '../../constants.js';
+import { maxMipLevelCount } from '../../util/texture/base.js';
+
+import { ValidationTest } from './validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('zero_size_and_usage')
+ .desc(
+ `Test texture creation with zero or nonzero size of
+ width, height, depthOrArrayLayers and mipLevelCount, usage for every dimension, and
+ representative formats.
+ `
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, ...kTextureDimensions])
+ .combine('format', ['rgba8unorm', 'rgb10a2unorm', 'bc1-rgba-unorm', 'depth24plus-stencil8'])
+ .beginSubcases()
+ .combine('zeroArgument', [
+ 'none',
+ 'width',
+ 'height',
+ 'depthOrArrayLayers',
+ 'mipLevelCount',
+ 'usage',
+ ])
+
+ // Filter out incompatible dimension type and format combinations.
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, zeroArgument, format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const size = [info.blockWidth, info.blockHeight, 1];
+ let mipLevelCount = 1;
+ let usage = GPUTextureUsage.TEXTURE_BINDING;
+
+ switch (zeroArgument) {
+ case 'width':
+ size[0] = 0;
+ break;
+ case 'height':
+ size[1] = 0;
+ break;
+ case 'depthOrArrayLayers':
+ size[2] = 0;
+ break;
+ case 'mipLevelCount':
+ mipLevelCount = 0;
+ break;
+ case 'usage':
+ usage = 0;
+ break;
+ default:
+ break;
+ }
+
+ const descriptor = {
+ size,
+ mipLevelCount,
+ dimension,
+ format,
+ usage,
+ };
+
+ const success = zeroArgument === 'none';
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('dimension_type_and_format_compatibility')
+ .desc(
+ `Test every dimension type on every format. Note that compressed formats and depth/stencil formats are not valid for 1D/3D dimension types.`
+ )
+ .params(u =>
+ u.combine('dimension', [undefined, ...kTextureDimensions]).combine('format', kTextureFormats)
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = {
+ size: [info.blockWidth, info.blockHeight, 1],
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !textureDimensionAndFormatCompatible(dimension, format));
+ });
+
+g.test('mipLevelCount,format')
+ .desc(
+ `Test texture creation with no mipmap chain, partial mipmap chain, full mipmap chain, out-of-bounds mipmap chain
+ for every format with different texture dimension types.`
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, ...kTextureDimensions])
+ .combine('format', kTextureFormats)
+ .beginSubcases()
+ .combine('mipLevelCount', [1, 2, 3, 6, 7])
+ // Filter out incompatible dimension type and format combinations.
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .combine('largestDimension', [0, 1, 2])
+ .unless(({ dimension, largestDimension }) => dimension === '1d' && largestDimension > 0)
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, mipLevelCount, largestDimension } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ // Compute dimensions such that the dimensions are in range [17, 32] and aligned with the
+ // format block size so that there will be exactly 6 mip levels.
+ const kTargetMipLevelCount = 5;
+ const kTargetLargeSize = (1 << kTargetMipLevelCount) - 1;
+ const largeSize = [
+ Math.floor(kTargetLargeSize / info.blockWidth) * info.blockWidth,
+ Math.floor(kTargetLargeSize / info.blockHeight) * info.blockHeight,
+ kTargetLargeSize,
+ ];
+
+ assert(17 <= largeSize[0] && largeSize[0] <= 32);
+ assert(17 <= largeSize[1] && largeSize[1] <= 32);
+
+ // Note that compressed formats are not valid for 1D. They have already been filtered out for 1D
+ // in this test. So there is no dilemma about size.width equals 1 vs
+ // size.width % info.blockHeight equals 0 for 1D compressed formats.
+ const size = [info.blockWidth, info.blockHeight, 1];
+ size[largestDimension] = largeSize[largestDimension];
+
+ const descriptor = {
+ size,
+ mipLevelCount,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success = mipLevelCount <= maxMipLevelCount(descriptor);
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('mipLevelCount,bound_check')
+ .desc(
+ `Test mip level count bound check upon different texture size and different texture dimension types.
+ The cases below test: 1) there must be no mip levels after a 1 level (1D texture), or 1x1 level (2D texture), or 1x1x1 level (3D texture), 2) array layers are not mip-mapped, 3) power-of-two, non-power-of-two, and non-square sizes.`
+ )
+ .params(u =>
+ u //
+ .combine('format', ['rgba8unorm', 'bc1-rgba-unorm'])
+ .beginSubcases()
+ .combineWithParams([
+ { size: [32, 32] }, // Mip level sizes: 32x32, 16x16, 8x8, 4x4, 2x2, 1x1
+ { size: [31, 32] }, // Mip level sizes: 31x32, 15x16, 7x8, 3x4, 1x2, 1x1
+ { size: [28, 32] }, // Mip level sizes: 28x32, 14x16, 7x8, 3x4, 1x2, 1x1
+ { size: [32, 31] }, // Mip level sizes: 32x31, 16x15, 8x7, 4x3, 2x1, 1x1
+ { size: [32, 28] }, // Mip level sizes: 32x28, 16x14, 8x7, 4x3, 2x1, 1x1
+ { size: [31, 31] }, // Mip level sizes: 31x31, 15x15, 7x7, 3x3, 1x1
+ { size: [32], dimension: '1d' }, // Mip level sizes: 32, 16, 8, 4, 2, 1
+ { size: [31], dimension: '1d' }, // Mip level sizes: 31, 15, 7, 3, 1
+ { size: [32, 32, 32], dimension: '3d' }, // Mip level sizes: 32x32x32, 16x16x16, 8x8x8, 4x4x4, 2x2x2, 1x1x1
+ { size: [32, 31, 31], dimension: '3d' }, // Mip level sizes: 32x31x31, 16x15x15, 8x7x7, 4x3x3, 2x1x1, 1x1x1
+ { size: [31, 32, 31], dimension: '3d' }, // Mip level sizes: 31x32x31, 15x16x15, 7x8x7, 3x4x3, 1x2x1, 1x1x1
+ { size: [31, 31, 32], dimension: '3d' }, // Mip level sizes: 31x31x32, 15x15x16, 7x7x8, 3x3x4, 1x1x2, 1x1x1
+ { size: [31, 31, 31], dimension: '3d' }, // Mip level sizes: 31x31x31, 15x15x15, 7x7x7, 3x3x3, 1x1x1
+ { size: [32, 8] }, // Mip levels: 32x8, 16x4, 8x2, 4x1, 2x1, 1x1
+ { size: [32, 32, 64] }, // Mip levels: 32x32x64, 16x16x64, 8x8x64, 4x4x64, 2x2x64, 1x1x64
+ { size: [32, 32, 64], dimension: '3d' }, // Mip levels: 32x32x64, 16x16x32, 8x8x16, 4x4x8, 2x2x4, 1x1x2, 1x1x1
+ ])
+ .unless(
+ ({ format, size, dimension }) =>
+ format === 'bc1-rgba-unorm' &&
+ (dimension === '1d' ||
+ dimension === '3d' ||
+ size[0] % kTextureFormatInfo[format].blockWidth !== 0 ||
+ size[1] % kTextureFormatInfo[format].blockHeight !== 0)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, size, dimension } = t.params;
+
+ const descriptor = {
+ size,
+ mipLevelCount: 0,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const mipLevelCount = maxMipLevelCount(descriptor);
+ descriptor.mipLevelCount = mipLevelCount;
+ t.device.createTexture(descriptor);
+
+ descriptor.mipLevelCount = mipLevelCount + 1;
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ });
+ });
+
+g.test('mipLevelCount,bound_check,bigger_than_integer_bit_width')
+ .desc(`Test mip level count bound check when mipLevelCount is bigger than integer bit width`)
+ .fn(async t => {
+ const descriptor = {
+ size: [32, 32],
+ mipLevelCount: 100,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ });
+ });
+
+g.test('sampleCount,various_sampleCount_with_all_formats')
+ .desc(
+ `Test texture creation with various (valid or invalid) sample count and all formats. Note that 1D and 3D textures can't support multisample.`
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, '2d'])
+ .combine('format', kTextureFormats)
+ .beginSubcases()
+ .combine('sampleCount', [0, 1, 2, 4, 8, 16, 32, 256])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, sampleCount, format } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+
+ const usage =
+ sampleCount > 1
+ ? GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT
+ : GPUTextureUsage.TEXTURE_BINDING;
+ const descriptor = {
+ size: [32 * blockWidth, 32 * blockHeight, 1],
+ sampleCount,
+ dimension,
+ format,
+ usage,
+ };
+
+ const success =
+ sampleCount === 1 ||
+ (sampleCount === 4 &&
+ kTextureFormatInfo[format].multisample &&
+ kTextureFormatInfo[format].renderable);
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('sampleCount,valid_sampleCount_with_other_parameter_varies')
+ .desc(
+ `Test texture creation with valid sample count when dimensions, arrayLayerCount, mipLevelCount,
+ format, and usage varies. Texture can be single sample (sampleCount is 1) or multi-sample
+ (sampleCount is 4). Multisample texture requires that
+ 1) its dimension is 2d or undefined,
+ 2) its format supports multisample,
+ 3) its mipLevelCount and arrayLayerCount are 1,
+ 4) its usage doesn't include STORAGE_BINDING,
+ 5) its usage includes RENDER_ATTACHMENT.`
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, ...kTextureDimensions])
+ .combine('format', kTextureFormats)
+ .beginSubcases()
+ .combine('sampleCount', [1, 4])
+ .combine('arrayLayerCount', [1, 2])
+ .unless(
+ ({ dimension, arrayLayerCount }) =>
+ arrayLayerCount === 2 && dimension !== '2d' && dimension !== undefined
+ )
+ .combine('mipLevelCount', [1, 2])
+ .expand('usage', p => {
+ const usageSet = new Set();
+ for (const usage0 of kTextureUsages) {
+ for (const usage1 of kTextureUsages) {
+ usageSet.add(usage0 | usage1);
+ }
+ }
+ return usageSet;
+ })
+ // Filter out incompatible dimension type and format combinations.
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .unless(({ usage, format, mipLevelCount, dimension }) => {
+ const info = kTextureFormatInfo[format];
+ return (
+ ((usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 &&
+ (!info.renderable || dimension !== '2d')) ||
+ ((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !info.storage) ||
+ (mipLevelCount !== 1 && dimension === '1d')
+ );
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, sampleCount, format, mipLevelCount, arrayLayerCount, usage } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+
+ const size =
+ dimension === '1d'
+ ? [32 * blockWidth, 1 * blockHeight, 1]
+ : dimension === '2d' || dimension === undefined
+ ? [32 * blockWidth, 32 * blockHeight, arrayLayerCount]
+ : [32 * blockWidth, 32 * blockHeight, 32];
+ const descriptor = {
+ size,
+ mipLevelCount,
+ sampleCount,
+ dimension,
+ format,
+ usage,
+ };
+
+ const success =
+ sampleCount === 1 ||
+ (sampleCount === 4 &&
+ (dimension === '2d' || dimension === undefined) &&
+ kTextureFormatInfo[format].multisample &&
+ mipLevelCount === 1 &&
+ arrayLayerCount === 1 &&
+ (usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 &&
+ (usage & GPUConst.TextureUsage.STORAGE_BINDING) === 0);
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('sample_count,1d_2d_array_3d')
+ .desc(`Test that you can not create 1d, 2d_array, and 3d multisampled textures`)
+ .params(u =>
+ u.combineWithParams([
+ { dimension: '2d', size: [4, 4, 1], shouldError: false },
+ { dimension: '1d', size: [4, 1, 1], shouldError: true },
+ { dimension: '2d', size: [4, 4, 4], shouldError: true },
+ { dimension: '2d', size: [4, 4, 6], shouldError: true },
+ { dimension: '3d', size: [4, 4, 4], shouldError: true },
+ ])
+ )
+ .fn(async t => {
+ const { dimension, size, shouldError } = t.params;
+
+ t.expectValidationError(() => {
+ t.device.createTexture({
+ size,
+ dimension,
+ sampleCount: 4,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ }, shouldError);
+ });
+
+g.test('texture_size,default_value_and_smallest_size,uncompressed_format')
+ .desc(
+ `Test default values for height and depthOrArrayLayers for every dimension type and every uncompressed format.
+ It also tests smallest size (lower bound) for every dimension type and every uncompressed format, while other texture_size tests are testing the upper bound.`
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, ...kTextureDimensions])
+ .combine('format', kUncompressedTextureFormats)
+ .beginSubcases()
+ .combine('size', [[1], [1, 1], [1, 1, 1]])
+ // Filter out incompatible dimension type and format combinations.
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, size } = t.params;
+
+ const descriptor = {
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ t.device.createTexture(descriptor);
+ });
+
+g.test('texture_size,default_value_and_smallest_size,compressed_format')
+ .desc(
+ `Test default values for height and depthOrArrayLayers for every dimension type and every compressed format.
+ It also tests smallest size (lower bound) for every dimension type and every compressed format, while other texture_size tests are testing the upper bound.`
+ )
+ .params(u =>
+ u
+ // Compressed formats are invalid for 1D and 3D.
+ .combine('dimension', [undefined, '2d'])
+ .combine('format', kCompressedTextureFormats)
+ .beginSubcases()
+ .expandWithParams(p => {
+ const { blockWidth, blockHeight } = kTextureFormatInfo[p.format];
+ return [
+ { size: [1], _success: false },
+ { size: [blockWidth], _success: false },
+ { size: [1, 1], _success: false },
+ { size: [blockWidth, blockHeight], _success: true },
+ { size: [1, 1, 1], _success: false },
+ { size: [blockWidth, blockHeight, 1], _success: true },
+ ];
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, size, _success } = t.params;
+
+ const descriptor = {
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !_success);
+ });
+
+g.test('texture_size,1d_texture')
+ .desc(`Test texture size requirement for 1D texture`)
+ .params(u =>
+ u //
+ // Compressed and depth-stencil textures are invalid for 1D.
+ .combine('format', kRegularTextureFormats)
+ .beginSubcases()
+ .combine('width', [
+ kLimitInfo.maxTextureDimension1D.default - 1,
+ kLimitInfo.maxTextureDimension1D.default,
+ kLimitInfo.maxTextureDimension1D.default + 1,
+ ])
+ .combine('height', [1, 2])
+ .combine('depthOrArrayLayers', [1, 2])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, width, height, depthOrArrayLayers } = t.params;
+
+ const descriptor = {
+ size: [width, height, depthOrArrayLayers],
+ dimension: '1d',
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success =
+ width <= kLimitInfo.maxTextureDimension1D.default && height === 1 && depthOrArrayLayers === 1;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('texture_size,2d_texture,uncompressed_format')
+ .desc(`Test texture size requirement for 2D texture with uncompressed format.`)
+ .params(u =>
+ u
+ .combine('dimension', [undefined, '2d'])
+ .combine('format', kUncompressedTextureFormats)
+ .combine('size', [
+ // Test the bound of width
+ [kLimitInfo.maxTextureDimension2D.default - 1, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default + 1, 1, 1],
+ // Test the bound of height
+ [1, kLimitInfo.maxTextureDimension2D.default - 1, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default + 1, 1],
+ // Test the bound of array layers
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default - 1],
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default],
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default + 1],
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, size } = t.params;
+
+ const descriptor = {
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success =
+ size[0] <= kLimitInfo.maxTextureDimension2D.default &&
+ size[1] <= kLimitInfo.maxTextureDimension2D.default &&
+ size[2] <= kLimitInfo.maxTextureArrayLayers.default;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('texture_size,2d_texture,compressed_format')
+ .desc(`Test texture size requirement for 2D texture with compressed format.`)
+ .params(u =>
+ u
+ .combine('dimension', [undefined, '2d'])
+ .combine('format', kCompressedTextureFormats)
+ .expand('size', p => {
+ const { blockWidth, blockHeight } = kTextureFormatInfo[p.format];
+ return [
+ // Test the bound of width
+ [kLimitInfo.maxTextureDimension2D.default - 1, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default - blockWidth, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default - blockWidth, blockHeight, 1],
+ [kLimitInfo.maxTextureDimension2D.default, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default, blockHeight, 1],
+ [kLimitInfo.maxTextureDimension2D.default + 1, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default + blockWidth, 1, 1],
+ [kLimitInfo.maxTextureDimension2D.default + blockWidth, blockHeight, 1],
+ // Test the bound of height
+ [1, kLimitInfo.maxTextureDimension2D.default - 1, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default - blockHeight, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension2D.default - blockHeight, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension2D.default, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default + 1, 1],
+ [1, kLimitInfo.maxTextureDimension2D.default + blockWidth, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension2D.default + blockHeight, 1],
+ // Test the bound of array layers
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default - 1],
+ [blockWidth, 1, kLimitInfo.maxTextureArrayLayers.default - 1],
+ [1, blockHeight, kLimitInfo.maxTextureArrayLayers.default - 1],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureArrayLayers.default - 1],
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default],
+ [blockWidth, 1, kLimitInfo.maxTextureArrayLayers.default],
+ [1, blockHeight, kLimitInfo.maxTextureArrayLayers.default],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureArrayLayers.default],
+ [1, 1, kLimitInfo.maxTextureArrayLayers.default + 1],
+ [blockWidth, 1, kLimitInfo.maxTextureArrayLayers.default + 1],
+ [1, blockHeight, kLimitInfo.maxTextureArrayLayers.default + 1],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureArrayLayers.default + 1],
+ ];
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, size } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = {
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success =
+ size[0] % info.blockWidth === 0 &&
+ size[1] % info.blockHeight === 0 &&
+ size[0] <= kLimitInfo.maxTextureDimension2D.default &&
+ size[1] <= kLimitInfo.maxTextureDimension2D.default &&
+ size[2] <= kLimitInfo.maxTextureArrayLayers.default;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('texture_size,3d_texture,uncompressed_format')
+ .desc(
+ `Test texture size requirement for 3D texture with uncompressed format. Note that depth/stencil formats are invalid for 3D textures, so we only test regular formats.`
+ )
+ .params(u =>
+ u //
+ .combine('format', kRegularTextureFormats)
+ .beginSubcases()
+ .combine('size', [
+ // Test the bound of width
+ [kLimitInfo.maxTextureDimension3D.default - 1, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default + 1, 1, 1],
+ // Test the bound of height
+ [1, kLimitInfo.maxTextureDimension3D.default - 1, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default + 1, 1],
+ // Test the bound of depth
+ [1, 1, kLimitInfo.maxTextureDimension3D.default - 1],
+ [1, 1, kLimitInfo.maxTextureDimension3D.default],
+ [1, 1, kLimitInfo.maxTextureDimension3D.default + 1],
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, size } = t.params;
+
+ const descriptor = {
+ size,
+ dimension: '3d',
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success =
+ size[0] <= kLimitInfo.maxTextureDimension3D.default &&
+ size[1] <= kLimitInfo.maxTextureDimension3D.default &&
+ size[2] <= kLimitInfo.maxTextureDimension3D.default;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('texture_size,3d_texture,compressed_format')
+ .desc(`Test texture size requirement for 3D texture with compressed format.`)
+ .params(u =>
+ u //
+ .combine('format', kCompressedTextureFormats)
+ .beginSubcases()
+ .expand('size', p => {
+ const { blockWidth, blockHeight } = kTextureFormatInfo[p.format];
+ return [
+ // Test the bound of width
+ [kLimitInfo.maxTextureDimension3D.default - 1, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default - blockWidth, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default - blockWidth, blockHeight, 1],
+ [kLimitInfo.maxTextureDimension3D.default, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default, blockHeight, 1],
+ [kLimitInfo.maxTextureDimension3D.default + 1, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default + blockWidth, 1, 1],
+ [kLimitInfo.maxTextureDimension3D.default + blockWidth, blockHeight, 1],
+ // Test the bound of height
+ [1, kLimitInfo.maxTextureDimension3D.default - 1, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default - blockHeight, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension3D.default - blockHeight, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension3D.default, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default + 1, 1],
+ [1, kLimitInfo.maxTextureDimension3D.default + blockWidth, 1],
+ [blockWidth, kLimitInfo.maxTextureDimension3D.default + blockHeight, 1],
+ // Test the bound of depth
+ [1, 1, kLimitInfo.maxTextureDimension3D.default - 1],
+ [blockWidth, 1, kLimitInfo.maxTextureDimension3D.default - 1],
+ [1, blockHeight, kLimitInfo.maxTextureDimension3D.default - 1],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureDimension3D.default - 1],
+ [1, 1, kLimitInfo.maxTextureDimension3D.default],
+ [blockWidth, 1, kLimitInfo.maxTextureDimension3D.default],
+ [1, blockHeight, kLimitInfo.maxTextureDimension3D.default],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureDimension3D.default],
+ [1, 1, kLimitInfo.maxTextureDimension3D.default + 1],
+ [blockWidth, 1, kLimitInfo.maxTextureDimension3D.default + 1],
+ [1, blockHeight, kLimitInfo.maxTextureDimension3D.default + 1],
+ [blockWidth, blockHeight, kLimitInfo.maxTextureDimension3D.default + 1],
+ ];
+ })
+ )
+ .beforeAllSubcases(t => {
+ // Compressed formats are not supported in 3D in WebGPU v1 because they are complicated but not very useful for now.
+ throw new SkipTestCase('Compressed 3D texture is not supported');
+
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, size } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ assert(
+ kLimitInfo.maxTextureDimension3D.default % info.blockWidth === 0 &&
+ kLimitInfo.maxTextureDimension3D.default % info.blockHeight === 0
+ );
+
+ const descriptor = {
+ size,
+ dimension: '3d',
+ format,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const success =
+ size[0] % info.blockWidth === 0 &&
+ size[1] % info.blockHeight === 0 &&
+ size[0] <= kLimitInfo.maxTextureDimension3D.default &&
+ size[1] <= kLimitInfo.maxTextureDimension3D.default &&
+ size[2] <= kLimitInfo.maxTextureDimension3D.default;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('texture_usage')
+ .desc(
+ `Test texture usage (single usage or combined usages) for every texture format and every dimension type`
+ )
+ .params(u =>
+ u
+ .combine('dimension', [undefined, ...kTextureDimensions])
+ .combine('format', kTextureFormats)
+ .beginSubcases()
+ // If usage0 and usage1 are the same, then the usage being test is a single usage. Otherwise, it is a combined usage.
+ .combine('usage0', kTextureUsages)
+ .combine('usage1', kTextureUsages)
+ // Filter out incompatible dimension type and format combinations.
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { dimension, format, usage0, usage1 } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const size = [info.blockWidth, info.blockHeight, 1];
+ const usage = usage0 | usage1;
+ const descriptor = {
+ size,
+ dimension,
+ format,
+ usage,
+ };
+
+ let success = true;
+ const appliedDimension = dimension ?? '2d';
+ // Note that we unconditionally test copy usages for all formats. We don't check copySrc/copyDst in kTextureFormatInfo in capability_info.js
+ // if (!info.copySrc && (usage & GPUTextureUsage.COPY_SRC) !== 0) success = false;
+ // if (!info.copyDst && (usage & GPUTextureUsage.COPY_DST) !== 0) success = false;
+ if (!info.storage && (usage & GPUTextureUsage.STORAGE_BINDING) !== 0) success = false;
+ if (
+ (!info.renderable || appliedDimension !== '2d') &&
+ (usage & GPUTextureUsage.RENDER_ATTACHMENT) !== 0
+ )
+ success = false;
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !success);
+ });
+
+g.test('viewFormats')
+ .desc(
+ `Test creating a texture with viewFormats list for all {texture format}x{view format}. Only compatible view formats should be valid.`
+ )
+ .params(u =>
+ u
+ .combine('formatFeature', kFeaturesForFormats)
+ .combine('viewFormatFeature', kFeaturesForFormats)
+ .beginSubcases()
+ .expand('format', ({ formatFeature }) =>
+ filterFormatsByFeature(formatFeature, kTextureFormats)
+ )
+ .expand('viewFormat', ({ viewFormatFeature }) =>
+ filterFormatsByFeature(viewFormatFeature, kTextureFormats)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { formatFeature, viewFormatFeature } = t.params;
+ t.selectDeviceOrSkipTestCase([formatFeature, viewFormatFeature]);
+ })
+ .fn(async t => {
+ const { format, viewFormat } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+
+ const compatible = viewCompatible(format, viewFormat);
+
+ // Test the viewFormat in the list.
+ t.expectValidationError(() => {
+ t.device.createTexture({
+ format,
+ size: [blockWidth, blockHeight],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [viewFormat],
+ });
+ }, !compatible);
+
+ // Test the viewFormat and the texture format in the list.
+ t.expectValidationError(() => {
+ t.device.createTexture({
+ format,
+ size: [blockWidth, blockHeight],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [viewFormat, format],
+ });
+ }, !compatible);
+
+ // Test the viewFormat multiple times in the list.
+ t.expectValidationError(() => {
+ t.device.createTexture({
+ format,
+ size: [blockWidth, blockHeight],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [viewFormat, viewFormat],
+ });
+ }, !compatible);
+ });
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
new file mode 100644
index 0000000000..2cee56b1ee
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/createView.spec.js
@@ -0,0 +1,333 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `createView validation tests.`;
+import { kUnitCaseParamsBuilder } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { unreachable } from '../../../common/util/util.js';
+import {
+ kTextureAspects,
+ kTextureDimensions,
+ kTextureFormatInfo,
+ kTextureFormats,
+ kTextureViewDimensions,
+ kFeaturesForFormats,
+ viewCompatible,
+ filterFormatsByFeature,
+} from '../../capability_info.js';
+import { kResourceStates } from '../../gpu_test.js';
+import {
+ getTextureDimensionFromView,
+ reifyTextureViewDescriptor,
+ viewDimensionsForTextureDimension,
+} from '../../util/texture/base.js';
+import { reifyExtent3D } from '../../util/unions.js';
+
+import { ValidationTest } from './validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+const kLevels = 6;
+
+g.test('format')
+ .desc(
+ `Views must have the view format compatible with the base texture, for all {texture format}x{view format}.`
+ )
+ .params(u =>
+ u
+ .combine('textureFormatFeature', kFeaturesForFormats)
+ .combine('viewFormatFeature', kFeaturesForFormats)
+ .beginSubcases()
+ .expand('textureFormat', ({ textureFormatFeature }) =>
+ filterFormatsByFeature(textureFormatFeature, kTextureFormats)
+ )
+ .expand('viewFormat', ({ viewFormatFeature }) =>
+ filterFormatsByFeature(viewFormatFeature, [undefined, ...kTextureFormats])
+ )
+ .combine('useViewFormatList', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { textureFormatFeature, viewFormatFeature } = t.params;
+ t.selectDeviceOrSkipTestCase([textureFormatFeature, viewFormatFeature]);
+ })
+ .fn(async t => {
+ const { textureFormat, viewFormat, useViewFormatList } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[textureFormat];
+
+ const compatible = viewFormat === undefined || viewCompatible(textureFormat, viewFormat);
+
+ const texture = t.device.createTexture({
+ format: textureFormat,
+ size: [blockWidth, blockHeight],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+
+ // This is a test of createView, not createTexture. Don't pass viewFormats here that
+ // are not compatible, as that is tested in createTexture.spec.ts.
+ viewFormats:
+ useViewFormatList && compatible && viewFormat !== undefined ? [viewFormat] : undefined,
+ });
+
+ // Successful if there is no view format, no reinterpretation was required, or the formats are compatible
+ // and is was specified in the viewFormats list.
+ const success =
+ viewFormat === undefined || viewFormat === textureFormat || (compatible && useViewFormatList);
+ t.expectValidationError(() => {
+ texture.createView({ format: viewFormat });
+ }, !success);
+ });
+
+g.test('dimension')
+ .desc(
+ `For all {texture dimension}, {view dimension}, test that they must be compatible:
+ - 1d -> 1d
+ - 2d -> 2d, 2d-array, cube, or cube-array
+ - 3d -> 3d`
+ )
+ .params(u =>
+ u
+ .combine('textureDimension', kTextureDimensions)
+ .combine('viewDimension', [...kTextureViewDimensions, undefined])
+ )
+ .fn(t => {
+ const { textureDimension, viewDimension } = t.params;
+
+ const size = textureDimension === '1d' ? [4] : [4, 4, 6];
+ const textureDescriptor = {
+ format: 'rgba8unorm',
+ dimension: textureDimension,
+ size,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+ const texture = t.device.createTexture(textureDescriptor);
+
+ const view = { dimension: viewDimension };
+ const reified = reifyTextureViewDescriptor(textureDescriptor, view);
+
+ const success = getTextureDimensionFromView(reified.dimension) === textureDimension;
+ t.expectValidationError(() => {
+ texture.createView(view);
+ }, !success);
+ });
+
+g.test('aspect')
+ .desc(
+ `For every {format}x{aspect}, test that the view aspect must exist in the format:
+ - "all" is allowed for any format
+ - "depth-only" is allowed only for depth and depth-stencil formats
+ - "stencil-only" is allowed only for stencil and depth-stencil formats`
+ )
+ .params(u =>
+ u //
+ .combine('format', kTextureFormats)
+ .combine('aspect', kTextureAspects)
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const { format, aspect } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const texture = t.device.createTexture({
+ format,
+ size: [info.blockWidth, info.blockHeight, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ const success =
+ aspect === 'all' ||
+ (aspect === 'depth-only' && info.depth) ||
+ (aspect === 'stencil-only' && info.stencil);
+ t.expectValidationError(() => {
+ texture.createView({ aspect });
+ }, !success);
+ });
+
+const kTextureAndViewDimensions = kUnitCaseParamsBuilder
+ .combine('textureDimension', kTextureDimensions)
+ .expand('viewDimension', p => [
+ undefined,
+ ...viewDimensionsForTextureDimension(p.textureDimension),
+ ]);
+
+function validateCreateViewLayersLevels(tex, view) {
+ const textureLevels = tex.mipLevelCount ?? 1;
+ const textureLayers = tex.dimension === '2d' ? reifyExtent3D(tex.size).depthOrArrayLayers : 1;
+ const reified = reifyTextureViewDescriptor(tex, view);
+
+ let success =
+ reified.mipLevelCount > 0 &&
+ reified.baseMipLevel < textureLevels &&
+ reified.baseMipLevel + reified.mipLevelCount <= textureLevels &&
+ reified.arrayLayerCount > 0 &&
+ reified.baseArrayLayer < textureLayers &&
+ reified.baseArrayLayer + reified.arrayLayerCount <= textureLayers;
+ if (reified.dimension === '1d' || reified.dimension === '2d' || reified.dimension === '3d') {
+ success &&= reified.arrayLayerCount === 1;
+ } else if (reified.dimension === 'cube') {
+ success &&= reified.arrayLayerCount === 6;
+ } else if (reified.dimension === 'cube-array') {
+ success &&= reified.arrayLayerCount % 6 === 0;
+ }
+ return success;
+}
+
+g.test('array_layers')
+ .desc(
+ `For each texture dimension {1d,2d,3d}, for each possible view dimension for that texture
+ dimension (or undefined, which defaults to the texture dimension), test validation of layer
+ counts:
+ - 1d, 2d, and 3d must have exactly 1 layer
+ - 2d-array must have 1 or more layers
+ - cube must have 6 layers
+ - cube-array must have a positive multiple of 6 layers
+ - Defaulting of baseArrayLayer and arrayLayerCount
+ - baseArrayLayer+arrayLayerCount must be within the texture`
+ )
+ .params(u =>
+ kTextureAndViewDimensions
+ .beginSubcases()
+ .expand('textureLayers', ({ textureDimension: d }) => (d === '2d' ? [1, 6, 18] : [1]))
+ .combine('textureLevels', [1, kLevels])
+ .unless(p => p.textureDimension === '1d' && p.textureLevels !== 1)
+ .expand(
+ 'baseArrayLayer',
+ ({ textureLayers: l }) => new Set([undefined, 0, 1, 5, 6, 7, l - 1, l, l + 1])
+ )
+ .expand('arrayLayerCount', function* ({ textureLayers: l, baseArrayLayer = 0 }) {
+ yield undefined;
+ for (const lastArrayLayer of new Set([0, 1, 5, 6, 7, l - 1, l, l + 1])) {
+ if (baseArrayLayer <= lastArrayLayer) yield lastArrayLayer - baseArrayLayer;
+ }
+ })
+ )
+ .fn(t => {
+ const {
+ textureDimension,
+ viewDimension,
+ textureLayers,
+ textureLevels,
+ baseArrayLayer,
+ arrayLayerCount,
+ } = t.params;
+
+ const kWidth = 1 << (kLevels - 1); // 32
+ const textureDescriptor = {
+ format: 'rgba8unorm',
+ dimension: textureDimension,
+ size:
+ textureDimension === '1d'
+ ? [kWidth]
+ : textureDimension === '2d'
+ ? [kWidth, kWidth, textureLayers]
+ : textureDimension === '3d'
+ ? [kWidth, kWidth, kWidth]
+ : unreachable(),
+ mipLevelCount: textureLevels,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const viewDescriptor = { dimension: viewDimension, baseArrayLayer, arrayLayerCount };
+ const success = validateCreateViewLayersLevels(textureDescriptor, viewDescriptor);
+
+ const texture = t.device.createTexture(textureDescriptor);
+ t.expectValidationError(() => {
+ texture.createView(viewDescriptor);
+ }, !success);
+ });
+
+g.test('mip_levels')
+ .desc(
+ `Views must have at least one level, and must be within the level of the base texture.
+
+ - mipLevelCount=0 at various baseMipLevel values
+ - Cases where baseMipLevel+mipLevelCount goes past the end of the texture
+ - Cases with baseMipLevel or mipLevelCount undefined (compares against reference defaulting impl)
+ `
+ )
+ .params(u =>
+ kTextureAndViewDimensions
+ .beginSubcases()
+ .combine('textureLevels', [1, kLevels - 2, kLevels])
+ .unless(p => p.textureDimension === '1d' && p.textureLevels !== 1)
+ .expand(
+ 'baseMipLevel',
+ ({ textureLevels: l }) => new Set([undefined, 0, 1, 5, 6, 7, l - 1, l, l + 1])
+ )
+ .expand('mipLevelCount', function* ({ textureLevels: l, baseMipLevel = 0 }) {
+ yield undefined;
+ for (const lastMipLevel of new Set([0, 1, 5, 6, 7, l - 1, l, l + 1])) {
+ if (baseMipLevel <= lastMipLevel) yield lastMipLevel - baseMipLevel;
+ }
+ })
+ )
+ .fn(t => {
+ const {
+ textureDimension,
+ viewDimension,
+ textureLevels,
+ baseMipLevel,
+ mipLevelCount,
+ } = t.params;
+
+ const textureDescriptor = {
+ format: 'rgba8unorm',
+ dimension: textureDimension,
+ size:
+ textureDimension === '1d' ? [32] : textureDimension === '3d' ? [32, 32, 32] : [32, 32, 18],
+ mipLevelCount: textureLevels,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ };
+
+ const viewDescriptor = { dimension: viewDimension, baseMipLevel, mipLevelCount };
+ const success = validateCreateViewLayersLevels(textureDescriptor, viewDescriptor);
+
+ const texture = t.device.createTexture(textureDescriptor);
+ t.debug(`${mipLevelCount} ${success}`);
+ t.expectValidationError(() => {
+ texture.createView(viewDescriptor);
+ }, !success);
+ });
+
+g.test('cube_faces_square')
+ .desc(
+ `Test that the X/Y dimensions of cube and cube array textures must be square.
+ - {2d (control case), cube, cube-array}`
+ )
+ .params(u =>
+ u //
+ .combine('dimension', ['2d', 'cube', 'cube-array'])
+ .combine('size', [
+ [4, 4, 6],
+ [5, 5, 6],
+ [4, 5, 6],
+ [4, 8, 6],
+ [8, 4, 6],
+ ])
+ )
+ .fn(async t => {
+ const { dimension, size } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ const success = dimension === '2d' || size[0] === size[1];
+ t.expectValidationError(() => {
+ texture.createView({ dimension });
+ }, !success);
+ });
+
+g.test('texture_state')
+ .desc(`createView should fail if the texture is invalid (but succeed if it is destroyed)`)
+ .paramsSubcasesOnly(u => u.combine('state', kResourceStates))
+ .fn(async t => {
+ const { state } = t.params;
+ const texture = t.createTextureWithState(state);
+
+ t.expectValidationError(() => {
+ texture.createView();
+ }, state === 'invalid');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/debugMarker.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/debugMarker.spec.js
new file mode 100644
index 0000000000..50a1fcadc6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/debugMarker.spec.js
@@ -0,0 +1,99 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test validation of pushDebugGroup, popDebugGroup, and insertDebugMarker.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+import { ValidationTest } from './validation_test.js';
+
+class F extends ValidationTest {
+ beginRenderPass(commandEncoder) {
+ const attachmentTexture = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ this.trackForCleanup(attachmentTexture);
+ return commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachmentTexture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('push_pop_call_count_unbalance,command_encoder')
+ .desc(
+ `
+ Test that a validation error is generated if {push,pop} debug group call count is not paired.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('pushCount', [1, 2, 3])
+ .combine('popCount', [1, 2, 3])
+ )
+ .fn(async t => {
+ const { pushCount, popCount } = t.params;
+
+ const encoder = t.device.createCommandEncoder();
+
+ for (let i = 0; i < pushCount; ++i) {
+ encoder.pushDebugGroup('EventStart');
+ }
+
+ encoder.insertDebugMarker('Marker');
+
+ for (let i = 0; i < popCount; ++i) {
+ encoder.popDebugGroup();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, pushCount !== popCount);
+ });
+
+g.test('push_pop_call_count_unbalance,render_compute_pass')
+ .desc(
+ `
+ Test that a validation error is generated if {push,pop} debug group call count is not paired in
+ ComputePassEncoder and RenderPassEncoder.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('passType', ['compute', 'render'])
+ .beginSubcases()
+ .combine('pushCount', [1, 2, 3])
+ .combine('popCount', [1, 2, 3])
+ )
+ .fn(async t => {
+ const { passType, pushCount, popCount } = t.params;
+
+ const encoder = t.device.createCommandEncoder();
+
+ const pass = passType === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder);
+
+ for (let i = 0; i < pushCount; ++i) {
+ pass.pushDebugGroup('EventStart');
+ }
+
+ pass.insertDebugMarker('Marker');
+
+ for (let i = 0; i < popCount; ++i) {
+ pass.popDebugGroup();
+ }
+
+ t.expectValidationError(() => {
+ pass.end();
+ encoder.finish();
+ }, pushCount !== popCount);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginComputePass.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginComputePass.spec.js
new file mode 100644
index 0000000000..1d5f6fce2e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginComputePass.spec.js
@@ -0,0 +1,194 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for validation in beginComputePass and GPUComputePassDescriptor as its optional descriptor.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kQueryTypes } from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+class F extends ValidationTest {
+ tryComputePass(success, descriptor) {
+ const encoder = this.device.createCommandEncoder();
+ const computePass = encoder.beginComputePass(descriptor);
+ computePass.end();
+
+ this.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('timestampWrites,same_location')
+ .desc(
+ `
+ Test that entries in timestampWrites do not have the same location in GPUComputePassDescriptor.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('locationA', ['beginning', 'end'])
+ .combine('locationB', ['beginning', 'end'])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { locationA, locationB } = t.params;
+
+ const querySet = t.device.createQuerySet({
+ type: 'timestamp',
+ count: 2,
+ });
+
+ const timestampWriteA = {
+ querySet,
+ queryIndex: 0,
+ location: locationA,
+ };
+
+ const timestampWriteB = {
+ querySet,
+ queryIndex: 1,
+ location: locationB,
+ };
+
+ const isValid = locationA !== locationB;
+
+ const descriptor = {
+ timestampWrites: [timestampWriteA, timestampWriteB],
+ };
+
+ t.tryComputePass(isValid, descriptor);
+ });
+
+g.test('timestampWrites,query_set_type')
+ .desc(
+ `
+ Test that all entries of the timestampWrites must have type 'timestamp'. If all query types are
+ not 'timestamp' in GPUComputePassDescriptor, a validation error should be generated.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('queryTypeA', kQueryTypes)
+ .combine('queryTypeB', kQueryTypes)
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForQueryTypeOrSkipTestCase([
+ 'timestamp',
+ t.params.queryTypeA,
+ t.params.queryTypeB,
+ ]);
+ })
+ .fn(async t => {
+ const { queryTypeA, queryTypeB } = t.params;
+
+ const timestampWriteA = {
+ querySet: t.device.createQuerySet({ type: queryTypeA, count: 1 }),
+ queryIndex: 0,
+ location: 'beginning',
+ };
+
+ const timestampWriteB = {
+ querySet: t.device.createQuerySet({ type: queryTypeB, count: 1 }),
+ queryIndex: 0,
+ location: 'end',
+ };
+
+ const isValid = queryTypeA === 'timestamp' && queryTypeB === 'timestamp';
+
+ const descriptor = {
+ timestampWrites: [timestampWriteA, timestampWriteB],
+ };
+
+ t.tryComputePass(isValid, descriptor);
+ });
+
+g.test('timestampWrites,invalid_query_set')
+ .desc(`Tests that timestampWrite that has an invalid query set generates a validation error.`)
+ .params(u => u.combine('querySetState', ['valid', 'invalid']))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { querySetState } = t.params;
+
+ const querySet = t.createQuerySetWithState(querySetState, {
+ type: 'timestamp',
+ count: 1,
+ });
+
+ const timestampWrite = {
+ querySet,
+ queryIndex: 0,
+ location: 'beginning',
+ };
+
+ const descriptor = {
+ timestampWrites: [timestampWrite],
+ };
+
+ t.tryComputePass(querySetState === 'valid', descriptor);
+ });
+
+g.test('timestampWrites,query_index_count')
+ .desc(`Test that querySet.count should be greater than timestampWrite.queryIndex.`)
+ .params(u => u.combine('queryIndex', [0, 1, 2, 3]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { queryIndex } = t.params;
+
+ const querySetCount = 2;
+
+ const timestampWrite = {
+ querySet: t.device.createQuerySet({ type: 'timestamp', count: querySetCount }),
+ queryIndex,
+ location: 'beginning',
+ };
+
+ const isValid = queryIndex < querySetCount;
+
+ const descriptor = {
+ timestampWrites: [timestampWrite],
+ };
+
+ t.tryComputePass(isValid, descriptor);
+ });
+
+g.test('timestamp_query_set,device_mismatch')
+ .desc(
+ `
+ Tests beginComputePass cannot be called with a timestamp query set created from another device.
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ t.selectMismatchedDeviceOrSkipTestCase('timestamp-query');
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const timestampQuerySet = sourceDevice.createQuerySet({
+ type: 'timestamp',
+ count: 1,
+ });
+
+ const timestampWrite = {
+ querySet: timestampQuerySet,
+ queryIndex: 0,
+ location: 'beginning',
+ };
+
+ const descriptor = {
+ timestampWrites: [timestampWrite],
+ };
+
+ t.tryComputePass(!mismatched, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginRenderPass.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginRenderPass.spec.js
new file mode 100644
index 0000000000..9a351bb5ce
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/beginRenderPass.spec.js
@@ -0,0 +1,213 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Note: render pass 'occlusionQuerySet' validation is tested in queries/general.spec.ts
+
+TODO: Check that depth-stencil attachment views must encompass all aspects.
+
+TODO: check for duplication (render_pass/, etc.), plan, and implement.
+Note possibly a lot of this should be operation tests instead.
+Notes:
+> - color attachments {zero, one, multiple}
+> - many different formats (some are non-renderable)
+> - is a view on a texture with multiple mip levels or array layers
+> - two attachments use the same view, or views of {intersecting, disjoint} ranges
+> - {without, with} resolve target
+> - resolve format compatibility with multisampled format
+> - {all possible load ops, load color {in range, negative, too large}}
+> - all possible store ops
+> - depth/stencil attachment
+> - {unset, all possible formats}
+> - {all possible {depth, stencil} load ops, load values {in range, negative, too large}}
+> - all possible {depth, stencil} store ops
+> - depthReadOnly {t,f}, stencilReadOnly {t,f}
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('color_attachments,device_mismatch')
+ .desc(
+ `
+ Tests beginRenderPass cannot be called with color attachments whose texture view or resolve target is created from another device
+ The 'view' and 'resolveTarget' are:
+ - created from same device in ColorAttachment0 and ColorAttachment1
+ - created from different device in ColorAttachment0 and ColorAttachment1
+ - created from same device in ColorAttachment0, but from different device in ColorAttachment1
+ `
+ )
+ .paramsSubcasesOnly([
+ {
+ view0Mismatched: false,
+ target0Mismatched: false,
+ view1Mismatched: false,
+ target1Mismatched: false,
+ }, // control case
+ {
+ view0Mismatched: false,
+ target0Mismatched: true,
+ view1Mismatched: false,
+ target1Mismatched: true,
+ },
+ {
+ view0Mismatched: true,
+ target0Mismatched: false,
+ view1Mismatched: true,
+ target1Mismatched: false,
+ },
+ {
+ view0Mismatched: false,
+ target0Mismatched: false,
+ view1Mismatched: false,
+ target1Mismatched: true,
+ },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { view0Mismatched, target0Mismatched, view1Mismatched, target1Mismatched } = t.params;
+ const mismatched = view0Mismatched || target0Mismatched || view1Mismatched || target1Mismatched;
+
+ const view0Texture = view0Mismatched
+ ? t.getDeviceMismatchedRenderTexture(4)
+ : t.getRenderTexture(4);
+ const target0Texture = target0Mismatched
+ ? t.getDeviceMismatchedRenderTexture()
+ : t.getRenderTexture();
+ const view1Texture = view1Mismatched
+ ? t.getDeviceMismatchedRenderTexture(4)
+ : t.getRenderTexture(4);
+ const target1Texture = target1Mismatched
+ ? t.getDeviceMismatchedRenderTexture()
+ : t.getRenderTexture();
+
+ const encoder = t.createEncoder('non-pass');
+ const pass = encoder.encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: view0Texture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ resolveTarget: target0Texture.createView(),
+ },
+ {
+ view: view1Texture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ resolveTarget: target1Texture.createView(),
+ },
+ ],
+ });
+ pass.end();
+
+ encoder.validateFinish(!mismatched);
+ });
+
+g.test('depth_stencil_attachment,device_mismatch')
+ .desc(
+ 'Tests beginRenderPass cannot be called with a depth stencil attachment whose texture view is created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+
+ const descriptor = {
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'depth24plus-stencil8',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ };
+
+ const depthStencilTexture = mismatched
+ ? t.getDeviceMismatchedTexture(descriptor)
+ : t.device.createTexture(descriptor);
+
+ const encoder = t.createEncoder('non-pass');
+ const pass = encoder.encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: depthStencilTexture.createView(),
+ depthClearValue: 0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilClearValue: 0,
+ stencilLoadOp: 'clear',
+ stencilStoreOp: 'store',
+ },
+ });
+ pass.end();
+
+ encoder.validateFinish(!mismatched);
+ });
+
+g.test('occlusion_query_set,device_mismatch')
+ .desc(
+ 'Tests beginRenderPass cannot be called with an occlusion query set created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const occlusionQuerySet = sourceDevice.createQuerySet({
+ type: 'occlusion',
+ count: 1,
+ });
+ t.trackForCleanup(occlusionQuerySet);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ encoder.validateFinish(!mismatched);
+ });
+
+g.test('timestamp_query_set,device_mismatch')
+ .desc(
+ `
+ Tests beginRenderPass cannot be called with a timestamp query set created from another device.
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ t.selectMismatchedDeviceOrSkipTestCase('timestamp-query');
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const timestampWrite = {
+ querySet: sourceDevice.createQuerySet({ type: 'timestamp', count: 1 }),
+ queryIndex: 0,
+ location: 'beginning',
+ };
+
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ const pass = encoder.encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+
+ timestampWrites: [timestampWrite],
+ });
+ pass.end();
+
+ encoder.validateFinish(!mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/clearBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/clearBuffer.spec.js
new file mode 100644
index 0000000000..c0a767e7ad
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/clearBuffer.spec.js
@@ -0,0 +1,242 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API validation tests for clearBuffer.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { kBufferUsages } from '../../../../capability_info.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { kMaxSafeMultipleOf8 } from '../../../../util/math.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ TestClearBuffer(options) {
+ const { buffer, offset, size, isSuccess } = options;
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.clearBuffer(buffer, offset, size);
+
+ this.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !isSuccess);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('buffer_state')
+ .desc(`Test that clearing an invalid or destroyed buffer fails.`)
+ .params(u => u.combine('bufferState', kResourceStates))
+ .fn(async t => {
+ const { bufferState } = t.params;
+
+ const buffer = t.createBufferWithState(bufferState, {
+ size: 8,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.clearBuffer(buffer, 0, 8);
+
+ if (bufferState === 'invalid') {
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ });
+ } else {
+ const cmd = commandEncoder.finish();
+ t.expectValidationError(() => {
+ t.device.queue.submit([cmd]);
+ }, bufferState === 'destroyed');
+ }
+ });
+
+g.test('buffer,device_mismatch')
+ .desc(`Tests clearBuffer cannot be called with buffer created from another device.`)
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+ const size = 8;
+
+ const buffer = sourceDevice.createBuffer({
+ size,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ t.TestClearBuffer({
+ buffer,
+ offset: 0,
+ size,
+ isSuccess: !mismatched,
+ });
+ });
+
+g.test('default_args')
+ .desc(`Test that calling clearBuffer with a default offset and size is valid.`)
+ .paramsSubcasesOnly([
+ { offset: undefined, size: undefined },
+ { offset: 4, size: undefined },
+ { offset: undefined, size: 8 },
+ ])
+ .fn(async t => {
+ const { offset, size } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset,
+ size,
+ isSuccess: true,
+ });
+ });
+
+g.test('buffer_usage')
+ .desc(`Test that only buffers with COPY_DST usage are valid to use with copyBuffers.`)
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('usage', kBufferUsages)
+ )
+ .fn(async t => {
+ const { usage } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset: 0,
+ size: 16,
+ isSuccess: usage === GPUBufferUsage.COPY_DST,
+ });
+ });
+
+g.test('size_alignment')
+ .desc(
+ `
+ Test that the clear size must be 4 byte aligned.
+ - Test size is not a multiple of 4.
+ - Test size is 0.
+ - Test size overflows the buffer size.
+ - Test size is omitted.
+ `
+ )
+ .paramsSubcasesOnly([
+ { size: 0, _isSuccess: true },
+ { size: 2, _isSuccess: false },
+ { size: 4, _isSuccess: true },
+ { size: 5, _isSuccess: false },
+ { size: 8, _isSuccess: true },
+ { size: 20, _isSuccess: false },
+ { size: undefined, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { size, _isSuccess: isSuccess } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset: 0,
+ size,
+ isSuccess,
+ });
+ });
+
+g.test('offset_alignment')
+ .desc(
+ `
+ Test that the clear offsets must be 4 byte aligned.
+ - Test offset is not a multiple of 4.
+ - Test offset is larger than the buffer size.
+ - Test offset is omitted.
+ `
+ )
+ .paramsSubcasesOnly([
+ { offset: 0, _isSuccess: true },
+ { offset: 2, _isSuccess: false },
+ { offset: 4, _isSuccess: true },
+ { offset: 5, _isSuccess: false },
+ { offset: 8, _isSuccess: true },
+ { offset: 20, _isSuccess: false },
+ { offset: undefined, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { offset, _isSuccess: isSuccess } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset,
+ size: 8,
+ isSuccess,
+ });
+ });
+
+g.test('overflow')
+ .desc(`Test that clears which may cause arthimetic overflows are invalid.`)
+ .paramsSubcasesOnly([
+ { offset: 0, size: kMaxSafeMultipleOf8 },
+ { offset: 16, size: kMaxSafeMultipleOf8 },
+ { offset: kMaxSafeMultipleOf8, size: 16 },
+ { offset: kMaxSafeMultipleOf8, size: kMaxSafeMultipleOf8 },
+ ])
+ .fn(async t => {
+ const { offset, size } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset,
+ size,
+ isSuccess: false,
+ });
+ });
+
+g.test('out_of_bounds')
+ .desc(`Test that clears which exceed the buffer bounds are invalid.`)
+ .paramsSubcasesOnly([
+ { offset: 0, size: 32, _isSuccess: true },
+ { offset: 0, size: 36 },
+ { offset: 32, size: 0, _isSuccess: true },
+ { offset: 32, size: 4 },
+ { offset: 36, size: 4 },
+ { offset: 36, size: 0 },
+ { offset: 20, size: 16 },
+ { offset: 20, size: 12, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { offset, size, _isSuccess = false } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 32,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestClearBuffer({
+ buffer,
+ offset,
+ size,
+ isSuccess: _isSuccess,
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/compute_pass.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/compute_pass.spec.js
new file mode 100644
index 0000000000..d3defb79a2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/compute_pass.spec.js
@@ -0,0 +1,251 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API validation test for compute pass
+
+Does **not** test usage scopes (resource_usages/) or programmable pass stuff (programmable_pass).
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { kBufferUsages, kLimitInfo } from '../../../../capability_info.js';
+import { GPUConst } from '../../../../constants.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ createComputePipeline(state) {
+ if (state === 'valid') {
+ return this.createNoOpComputePipeline();
+ }
+
+ return this.createErrorComputePipeline();
+ }
+
+ createIndirectBuffer(state, data) {
+ const descriptor = {
+ size: data.byteLength,
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST,
+ };
+
+ if (state === 'invalid') {
+ descriptor.usage = 0xffff; // Invalid GPUBufferUsage
+ }
+
+ this.device.pushErrorScope('validation');
+ const buffer = this.device.createBuffer(descriptor);
+ void this.device.popErrorScope();
+
+ if (state === 'valid') {
+ this.queue.writeBuffer(buffer, 0, data);
+ }
+
+ if (state === 'destroyed') {
+ buffer.destroy();
+ }
+
+ return buffer;
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('set_pipeline')
+ .desc(
+ `
+setPipeline should generate an error iff using an 'invalid' pipeline.
+`
+ )
+ .params(u => u.beginSubcases().combine('state', ['valid', 'invalid']))
+ .fn(t => {
+ const { state } = t.params;
+ const pipeline = t.createComputePipeline(state);
+
+ const { encoder, validateFinishAndSubmitGivenState } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmitGivenState(state);
+ });
+
+g.test('pipeline,device_mismatch')
+ .desc('Tests setPipeline cannot be called with a compute pipeline created from another device')
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const pipeline = sourceDevice.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: sourceDevice.createShaderModule({
+ code: '@compute @workgroup_size(1) fn main() {}',
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const { encoder, validateFinish } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+ validateFinish(!mismatched);
+ });
+
+const kMaxDispatch = kLimitInfo.maxComputeWorkgroupsPerDimension.default;
+g.test('dispatch_sizes')
+ .desc(
+ `Test 'direct' and 'indirect' dispatch with various sizes.
+
+ Only direct dispatches can produce validation errors.
+ Workgroup sizes:
+ - valid: { zero, one, just under limit }
+ - invalid: { just over limit, way over limit }
+
+ TODO: Verify that the invalid cases don't execute any invocations at all.
+`
+ )
+ .params(u =>
+ u
+ .combine('dispatchType', ['direct', 'indirect'])
+ .combine('largeDimValue', [0, 1, kMaxDispatch, kMaxDispatch + 1, 0x7fff_ffff, 0xffff_ffff])
+ .beginSubcases()
+ .combine('largeDimIndex', [0, 1, 2])
+ .combine('smallDimValue', [0, 1])
+ )
+ .fn(t => {
+ const { dispatchType, largeDimIndex, smallDimValue, largeDimValue } = t.params;
+
+ const pipeline = t.createNoOpComputePipeline();
+
+ const workSizes = [smallDimValue, smallDimValue, smallDimValue];
+ workSizes[largeDimIndex] = largeDimValue;
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+ if (dispatchType === 'direct') {
+ const [x, y, z] = workSizes;
+ encoder.dispatchWorkgroups(x, y, z);
+ } else if (dispatchType === 'indirect') {
+ encoder.dispatchWorkgroupsIndirect(
+ t.createIndirectBuffer('valid', new Uint32Array(workSizes)),
+ 0
+ );
+ }
+
+ const shouldError =
+ dispatchType === 'direct' &&
+ (workSizes[0] > kMaxDispatch || workSizes[1] > kMaxDispatch || workSizes[2] > kMaxDispatch);
+
+ validateFinishAndSubmit(!shouldError, true);
+ });
+
+const kBufferData = new Uint32Array(6).fill(1);
+g.test('indirect_dispatch_buffer_state')
+ .desc(
+ `
+Test dispatchWorkgroupsIndirect validation by submitting various dispatches with a no-op pipeline
+and an indirectBuffer with 6 elements.
+- indirectBuffer: {'valid', 'invalid', 'destroyed'}
+- indirectOffset:
+ - valid, within the buffer: {beginning, middle, end} of the buffer
+ - invalid, non-multiple of 4
+ - invalid, the last element is outside the buffer
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('state', kResourceStates)
+ .combine('offset', [
+ // valid (for 'valid' buffers)
+ 0,
+ Uint32Array.BYTES_PER_ELEMENT,
+ kBufferData.byteLength - 3 * Uint32Array.BYTES_PER_ELEMENT,
+ // invalid, non-multiple of 4 offset
+ 1,
+ // invalid, last element outside buffer
+ kBufferData.byteLength - 2 * Uint32Array.BYTES_PER_ELEMENT,
+ ])
+ )
+ .fn(t => {
+ const { state, offset } = t.params;
+ const pipeline = t.createNoOpComputePipeline();
+ const buffer = t.createIndirectBuffer(state, kBufferData);
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+ encoder.dispatchWorkgroupsIndirect(buffer, offset);
+
+ const finishShouldError =
+ state === 'invalid' ||
+ offset % 4 !== 0 ||
+ offset + 3 * Uint32Array.BYTES_PER_ELEMENT > kBufferData.byteLength;
+ validateFinishAndSubmit(!finishShouldError, state !== 'destroyed');
+ });
+
+g.test('indirect_dispatch_buffer,device_mismatch')
+ .desc(
+ `Tests dispatchWorkgroupsIndirect cannot be called with an indirect buffer created from another device`
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+
+ const pipeline = t.createNoOpComputePipeline();
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const buffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+ t.trackForCleanup(buffer);
+
+ const { encoder, validateFinish } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+ encoder.dispatchWorkgroupsIndirect(buffer, 0);
+ validateFinish(!mismatched);
+ });
+
+g.test('indirect_dispatch_buffer,usage')
+ .desc(
+ `
+ Tests dispatchWorkgroupsIndirect generates a validation error if the buffer usage does not
+ contain INDIRECT usage.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ // If bufferUsage0 and bufferUsage1 are the same, the usage being test is a single usage.
+ // Otherwise, it's a combined usage.
+ .combine('bufferUsage0', kBufferUsages)
+ .combine('bufferUsage1', kBufferUsages)
+ .unless(
+ ({ bufferUsage0, bufferUsage1 }) =>
+ ((bufferUsage0 | bufferUsage1) &
+ (GPUConst.BufferUsage.MAP_READ | GPUConst.BufferUsage.MAP_WRITE)) !==
+ 0
+ )
+ )
+ .fn(async t => {
+ const { bufferUsage0, bufferUsage1 } = t.params;
+
+ const bufferUsage = bufferUsage0 | bufferUsage1;
+
+ const layout = t.device.createPipelineLayout({ bindGroupLayouts: [] });
+ const pipeline = t.createNoOpComputePipeline(layout);
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: bufferUsage,
+ });
+ t.trackForCleanup(buffer);
+
+ const success = (GPUBufferUsage.INDIRECT & bufferUsage) !== 0;
+
+ const { encoder, validateFinish } = t.createEncoder('compute pass');
+ encoder.setPipeline(pipeline);
+
+ encoder.dispatchWorkgroupsIndirect(buffer, 0);
+ validateFinish(success);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.js
new file mode 100644
index 0000000000..75d7678b40
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.js
@@ -0,0 +1,320 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyBufferToBuffer tests.
+
+Test Plan:
+* Buffer is valid/invalid
+ - the source buffer is invalid
+ - the destination buffer is invalid
+* Buffer usages
+ - the source buffer is created without GPUBufferUsage::COPY_SRC
+ - the destination buffer is created without GPUBufferUsage::COPY_DEST
+* CopySize
+ - copySize is not a multiple of 4
+ - copySize is 0
+* copy offsets
+ - sourceOffset is not a multiple of 4
+ - destinationOffset is not a multiple of 4
+* Arithmetic overflow
+ - (sourceOffset + copySize) is overflow
+ - (destinationOffset + copySize) is overflow
+* Out of bounds
+ - (sourceOffset + copySize) > size of source buffer
+ - (destinationOffset + copySize) > size of destination buffer
+* Source buffer and destination buffer are the same buffer
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { kBufferUsages } from '../../../../capability_info.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { kMaxSafeMultipleOf8 } from '../../../../util/math.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ TestCopyBufferToBuffer(options) {
+ const { srcBuffer, srcOffset, dstBuffer, dstOffset, copySize, expectation } = options;
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyBufferToBuffer(srcBuffer, srcOffset, dstBuffer, dstOffset, copySize);
+
+ if (expectation === 'FinishError') {
+ this.expectValidationError(() => {
+ commandEncoder.finish();
+ });
+ } else {
+ const cmd = commandEncoder.finish();
+ this.expectValidationError(() => {
+ this.device.queue.submit([cmd]);
+ }, expectation === 'SubmitError');
+ }
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('buffer_state')
+ .params(u =>
+ u //
+ .combine('srcBufferState', kResourceStates)
+ .combine('dstBufferState', kResourceStates)
+ )
+ .fn(async t => {
+ const { srcBufferState, dstBufferState } = t.params;
+ const srcBuffer = t.createBufferWithState(srcBufferState, {
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ const dstBuffer = t.createBufferWithState(dstBufferState, {
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const shouldFinishError = srcBufferState === 'invalid' || dstBufferState === 'invalid';
+ const shouldSubmitSuccess = srcBufferState === 'valid' && dstBufferState === 'valid';
+ const expectation = shouldSubmitSuccess
+ ? 'Success'
+ : shouldFinishError
+ ? 'FinishError'
+ : 'SubmitError';
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset: 0,
+ dstBuffer,
+ dstOffset: 0,
+ copySize: 8,
+ expectation,
+ });
+ });
+
+g.test('buffer,device_mismatch')
+ .desc(
+ 'Tests copyBufferToBuffer cannot be called with src buffer or dst buffer created from another device'
+ )
+ .paramsSubcasesOnly([
+ { srcMismatched: false, dstMismatched: false }, // control case
+ { srcMismatched: true, dstMismatched: false },
+ { srcMismatched: false, dstMismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { srcMismatched, dstMismatched } = t.params;
+
+ const srcBufferDevice = srcMismatched ? t.mismatchedDevice : t.device;
+ const srcBuffer = srcBufferDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(srcBuffer);
+
+ const dstBufferDevice = dstMismatched ? t.mismatchedDevice : t.device;
+ const dstBuffer = dstBufferDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(dstBuffer);
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset: 0,
+ dstBuffer,
+ dstOffset: 0,
+ copySize: 8,
+ expectation: srcMismatched || dstMismatched ? 'FinishError' : 'Success',
+ });
+ });
+
+g.test('buffer_usage')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcUsage', kBufferUsages)
+ .combine('dstUsage', kBufferUsages)
+ )
+ .fn(async t => {
+ const { srcUsage, dstUsage } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 16,
+ usage: srcUsage,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 16,
+ usage: dstUsage,
+ });
+
+ const isSuccess = srcUsage === GPUBufferUsage.COPY_SRC && dstUsage === GPUBufferUsage.COPY_DST;
+ const expectation = isSuccess ? 'Success' : 'FinishError';
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset: 0,
+ dstBuffer,
+ dstOffset: 0,
+ copySize: 8,
+ expectation,
+ });
+ });
+
+g.test('copy_size_alignment')
+ .paramsSubcasesOnly([
+ { copySize: 0, _isSuccess: true },
+ { copySize: 2, _isSuccess: false },
+ { copySize: 4, _isSuccess: true },
+ { copySize: 5, _isSuccess: false },
+ { copySize: 8, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { copySize, _isSuccess: isSuccess } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset: 0,
+ dstBuffer,
+ dstOffset: 0,
+ copySize,
+ expectation: isSuccess ? 'Success' : 'FinishError',
+ });
+ });
+
+g.test('copy_offset_alignment')
+ .paramsSubcasesOnly([
+ { srcOffset: 0, dstOffset: 0, _isSuccess: true },
+ { srcOffset: 2, dstOffset: 0, _isSuccess: false },
+ { srcOffset: 4, dstOffset: 0, _isSuccess: true },
+ { srcOffset: 5, dstOffset: 0, _isSuccess: false },
+ { srcOffset: 8, dstOffset: 0, _isSuccess: true },
+ { srcOffset: 0, dstOffset: 2, _isSuccess: false },
+ { srcOffset: 0, dstOffset: 4, _isSuccess: true },
+ { srcOffset: 0, dstOffset: 5, _isSuccess: false },
+ { srcOffset: 0, dstOffset: 8, _isSuccess: true },
+ { srcOffset: 4, dstOffset: 4, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { srcOffset, dstOffset, _isSuccess: isSuccess } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset,
+ dstBuffer,
+ dstOffset,
+ copySize: 8,
+ expectation: isSuccess ? 'Success' : 'FinishError',
+ });
+ });
+
+g.test('copy_overflow')
+ .paramsSubcasesOnly([
+ { srcOffset: 0, dstOffset: 0, copySize: kMaxSafeMultipleOf8 },
+ { srcOffset: 16, dstOffset: 0, copySize: kMaxSafeMultipleOf8 },
+ { srcOffset: 0, dstOffset: 16, copySize: kMaxSafeMultipleOf8 },
+ { srcOffset: kMaxSafeMultipleOf8, dstOffset: 0, copySize: 16 },
+ { srcOffset: 0, dstOffset: kMaxSafeMultipleOf8, copySize: 16 },
+ { srcOffset: kMaxSafeMultipleOf8, dstOffset: 0, copySize: kMaxSafeMultipleOf8 },
+ { srcOffset: 0, dstOffset: kMaxSafeMultipleOf8, copySize: kMaxSafeMultipleOf8 },
+ {
+ srcOffset: kMaxSafeMultipleOf8,
+ dstOffset: kMaxSafeMultipleOf8,
+ copySize: kMaxSafeMultipleOf8,
+ },
+ ])
+ .fn(async t => {
+ const { srcOffset, dstOffset, copySize } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset,
+ dstBuffer,
+ dstOffset,
+ copySize,
+ expectation: 'FinishError',
+ });
+ });
+
+g.test('copy_out_of_bounds')
+ .paramsSubcasesOnly([
+ { srcOffset: 0, dstOffset: 0, copySize: 32, _isSuccess: true },
+ { srcOffset: 0, dstOffset: 0, copySize: 36 },
+ { srcOffset: 36, dstOffset: 0, copySize: 4 },
+ { srcOffset: 0, dstOffset: 36, copySize: 4 },
+ { srcOffset: 36, dstOffset: 0, copySize: 0 },
+ { srcOffset: 0, dstOffset: 36, copySize: 0 },
+ { srcOffset: 20, dstOffset: 0, copySize: 16 },
+ { srcOffset: 20, dstOffset: 0, copySize: 12, _isSuccess: true },
+ { srcOffset: 0, dstOffset: 20, copySize: 16 },
+ { srcOffset: 0, dstOffset: 20, copySize: 12, _isSuccess: true },
+ ])
+ .fn(async t => {
+ const { srcOffset, dstOffset, copySize, _isSuccess = false } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 32,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 32,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer,
+ srcOffset,
+ dstBuffer,
+ dstOffset,
+ copySize,
+ expectation: _isSuccess ? 'Success' : 'FinishError',
+ });
+ });
+
+g.test('copy_within_same_buffer')
+ .paramsSubcasesOnly([
+ { srcOffset: 0, dstOffset: 8, copySize: 4 },
+ { srcOffset: 8, dstOffset: 0, copySize: 4 },
+ { srcOffset: 0, dstOffset: 4, copySize: 8 },
+ { srcOffset: 4, dstOffset: 0, copySize: 8 },
+ ])
+ .fn(async t => {
+ const { srcOffset, dstOffset, copySize } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ t.TestCopyBufferToBuffer({
+ srcBuffer: buffer,
+ srcOffset,
+ dstBuffer: buffer,
+ dstOffset,
+ copySize,
+ expectation: 'FinishError',
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js
new file mode 100644
index 0000000000..e3576dab1f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.js
@@ -0,0 +1,873 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyTextureToTexture tests.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import {
+ kTextureFormatInfo,
+ kTextureFormats,
+ kCompressedTextureFormats,
+ kDepthStencilFormats,
+ kTextureUsages,
+ textureDimensionAndFormatCompatible,
+ kTextureDimensions,
+ kFeaturesForFormats,
+ filterFormatsByFeature,
+} from '../../../../capability_info.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { align, lcm } from '../../../../util/math.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ TestCopyTextureToTexture(source, destination, copySize, expectation) {
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToTexture(source, destination, copySize);
+
+ if (expectation === 'FinishError') {
+ this.expectValidationError(() => {
+ commandEncoder.finish();
+ });
+ } else {
+ const cmd = commandEncoder.finish();
+ this.expectValidationError(() => {
+ this.device.queue.submit([cmd]);
+ }, expectation === 'SubmitError');
+ }
+ }
+
+ GetPhysicalSubresourceSize(dimension, textureSize, format, mipLevel) {
+ const virtualWidthAtLevel = Math.max(textureSize.width >> mipLevel, 1);
+ const virtualHeightAtLevel = Math.max(textureSize.height >> mipLevel, 1);
+ const physicalWidthAtLevel = align(virtualWidthAtLevel, kTextureFormatInfo[format].blockWidth);
+ const physicalHeightAtLevel = align(
+ virtualHeightAtLevel,
+ kTextureFormatInfo[format].blockHeight
+ );
+
+ switch (dimension) {
+ case '1d':
+ return { width: physicalWidthAtLevel, height: 1, depthOrArrayLayers: 1 };
+ case '2d':
+ return {
+ width: physicalWidthAtLevel,
+ height: physicalHeightAtLevel,
+ depthOrArrayLayers: textureSize.depthOrArrayLayers,
+ };
+ case '3d':
+ return {
+ width: physicalWidthAtLevel,
+ height: physicalHeightAtLevel,
+ depthOrArrayLayers: Math.max(textureSize.depthOrArrayLayers >> mipLevel, 1),
+ };
+ }
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('copy_with_invalid_or_destroyed_texture')
+ .desc('Test copyTextureToTexture is an error when one of the textures is invalid or destroyed.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcState', kResourceStates)
+ .combine('dstState', kResourceStates)
+ )
+ .fn(async t => {
+ const { srcState, dstState } = t.params;
+
+ const textureDesc = {
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ };
+
+ const srcTexture = t.createTextureWithState(srcState, textureDesc);
+ const dstTexture = t.createTextureWithState(dstState, textureDesc);
+
+ const isSubmitSuccess = srcState === 'valid' && dstState === 'valid';
+ const isFinishSuccess = srcState !== 'invalid' && dstState !== 'invalid';
+ const expectation = isFinishSuccess
+ ? isSubmitSuccess
+ ? 'Success'
+ : 'SubmitError'
+ : 'FinishError';
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ expectation
+ );
+ });
+
+g.test('texture,device_mismatch')
+ .desc(
+ 'Tests copyTextureToTexture cannot be called with src texture or dst texture created from another device.'
+ )
+ .paramsSubcasesOnly([
+ { srcMismatched: false, dstMismatched: false }, // control case
+ { srcMismatched: true, dstMismatched: false },
+ { srcMismatched: false, dstMismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { srcMismatched, dstMismatched } = t.params;
+
+ const size = { width: 4, height: 4, depthOrArrayLayers: 1 };
+ const format = 'rgba8unorm';
+
+ const srcTextureDevice = srcMismatched ? t.mismatchedDevice : t.device;
+ const srcTexture = srcTextureDevice.createTexture({
+ size,
+ format,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ t.trackForCleanup(srcTexture);
+
+ const dstTextureDevice = dstMismatched ? t.mismatchedDevice : t.device;
+ const dstTexture = dstTextureDevice.createTexture({
+ size,
+ format,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+ t.trackForCleanup(dstTexture);
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ srcMismatched || dstMismatched ? 'FinishError' : 'Success'
+ );
+ });
+
+g.test('mipmap_level')
+ .desc(
+ `
+Test copyTextureToTexture must specify mipLevels that are in range.
+- for various dimensions
+- for various mip level count in the texture
+- for various copy target mip level (in range and not in range)
+`
+ )
+ .params(u =>
+ u //
+ .combine('dimension', kTextureDimensions)
+ .beginSubcases()
+ .combineWithParams([
+ { srcLevelCount: 1, dstLevelCount: 1, srcCopyLevel: 0, dstCopyLevel: 0 },
+ { srcLevelCount: 1, dstLevelCount: 1, srcCopyLevel: 1, dstCopyLevel: 0 },
+ { srcLevelCount: 1, dstLevelCount: 1, srcCopyLevel: 0, dstCopyLevel: 1 },
+ { srcLevelCount: 3, dstLevelCount: 3, srcCopyLevel: 0, dstCopyLevel: 0 },
+ { srcLevelCount: 3, dstLevelCount: 3, srcCopyLevel: 2, dstCopyLevel: 0 },
+ { srcLevelCount: 3, dstLevelCount: 3, srcCopyLevel: 3, dstCopyLevel: 0 },
+ { srcLevelCount: 3, dstLevelCount: 3, srcCopyLevel: 0, dstCopyLevel: 2 },
+ { srcLevelCount: 3, dstLevelCount: 3, srcCopyLevel: 0, dstCopyLevel: 3 },
+ ])
+ .unless(p => p.dimension === '1d' && (p.srcLevelCount !== 1 || p.dstLevelCount !== 1))
+ )
+ .fn(async t => {
+ const { srcLevelCount, dstLevelCount, srcCopyLevel, dstCopyLevel, dimension } = t.params;
+
+ const srcTexture = t.device.createTexture({
+ size: { width: 32, height: 1, depthOrArrayLayers: 1 },
+ dimension,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC,
+ mipLevelCount: srcLevelCount,
+ });
+ const dstTexture = t.device.createTexture({
+ size: { width: 32, height: 1, depthOrArrayLayers: 1 },
+ dimension,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST,
+ mipLevelCount: dstLevelCount,
+ });
+
+ const isSuccess = srcCopyLevel < srcLevelCount && dstCopyLevel < dstLevelCount;
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, mipLevel: srcCopyLevel },
+ { texture: dstTexture, mipLevel: dstCopyLevel },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('texture_usage')
+ .desc(
+ `
+Test that copyTextureToTexture source/destination need COPY_SRC/COPY_DST usages.
+- for all possible source texture usages
+- for all possible destination texture usages
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcUsage', kTextureUsages)
+ .combine('dstUsage', kTextureUsages)
+ )
+ .fn(async t => {
+ const { srcUsage, dstUsage } = t.params;
+
+ const srcTexture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: srcUsage,
+ });
+ const dstTexture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: dstUsage,
+ });
+
+ const isSuccess =
+ srcUsage === GPUTextureUsage.COPY_SRC && dstUsage === GPUTextureUsage.COPY_DST;
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('sample_count')
+ .desc(
+ `
+Test that textures in copyTextureToTexture must have the same sample count.
+- for various source texture sample count
+- for various destination texture sample count
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcSampleCount', [1, 4])
+ .combine('dstSampleCount', [1, 4])
+ )
+ .fn(async t => {
+ const { srcSampleCount, dstSampleCount } = t.params;
+
+ const srcTexture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: srcSampleCount,
+ });
+ const dstTexture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: dstSampleCount,
+ });
+
+ const isSuccess = srcSampleCount === dstSampleCount;
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ { width: 4, height: 4, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('multisampled_copy_restrictions')
+ .desc(
+ `
+Test that copyTextureToTexture of multisampled texture must copy a whole subresource to a whole subresource.
+- for various origin for the source and destination of the copies.
+
+Note: this is only tested for 2D textures as it is the only dimension compatible with multisampling.
+TODO: Check the source and destination constraints separately.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcCopyOrigin', [
+ { x: 0, y: 0, z: 0 },
+ { x: 1, y: 0, z: 0 },
+ { x: 0, y: 1, z: 0 },
+ { x: 1, y: 1, z: 0 },
+ ])
+ .combine('dstCopyOrigin', [
+ { x: 0, y: 0, z: 0 },
+ { x: 1, y: 0, z: 0 },
+ { x: 0, y: 1, z: 0 },
+ { x: 1, y: 1, z: 0 },
+ ])
+ .expand('copyWidth', p => [32 - Math.max(p.srcCopyOrigin.x, p.dstCopyOrigin.x), 16])
+ .expand('copyHeight', p => [16 - Math.max(p.srcCopyOrigin.y, p.dstCopyOrigin.y), 8])
+ )
+ .fn(async t => {
+ const { srcCopyOrigin, dstCopyOrigin, copyWidth, copyHeight } = t.params;
+
+ const kWidth = 32;
+ const kHeight = 16;
+
+ // Currently we don't support multisampled 2D array textures and the mipmap level count of the
+ // multisampled textures must be 1.
+ const srcTexture = t.device.createTexture({
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: 4,
+ });
+ const dstTexture = t.device.createTexture({
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: 4,
+ });
+
+ const isSuccess = copyWidth === kWidth && copyHeight === kHeight;
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: srcCopyOrigin },
+ { texture: dstTexture, origin: dstCopyOrigin },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('texture_format_compatibility')
+ .desc(
+ `
+Test the formats of textures in copyTextureToTexture must be copy-compatible.
+- for all source texture formats
+- for all destination texture formats
+`
+ )
+ .params(u =>
+ u
+ .combine('srcFormatFeature', kFeaturesForFormats)
+ .combine('dstFormatFeature', kFeaturesForFormats)
+ .beginSubcases()
+ .expand('srcFormat', ({ srcFormatFeature }) =>
+ filterFormatsByFeature(srcFormatFeature, kTextureFormats)
+ )
+ .expand('dstFormat', ({ dstFormatFeature }) =>
+ filterFormatsByFeature(dstFormatFeature, kTextureFormats)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { srcFormatFeature, dstFormatFeature } = t.params;
+ t.selectDeviceOrSkipTestCase([srcFormatFeature, dstFormatFeature]);
+ })
+ .fn(async t => {
+ const { srcFormat, dstFormat } = t.params;
+ const srcFormatInfo = kTextureFormatInfo[srcFormat];
+ const dstFormatInfo = kTextureFormatInfo[dstFormat];
+
+ const textureSize = {
+ width: lcm(srcFormatInfo.blockWidth, dstFormatInfo.blockWidth),
+ height: lcm(srcFormatInfo.blockHeight, dstFormatInfo.blockHeight),
+ depthOrArrayLayers: 1,
+ };
+
+ const srcTexture = t.device.createTexture({
+ size: textureSize,
+ format: srcFormat,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+
+ const dstTexture = t.device.createTexture({
+ size: textureSize,
+ format: dstFormat,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ // Allow copy between compatible format textures.
+ const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat ?? srcFormat;
+ const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat ?? dstFormat;
+ const isSuccess = srcBaseFormat === dstBaseFormat;
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ textureSize,
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('depth_stencil_copy_restrictions')
+ .desc(
+ `
+Test that depth textures subresources must be entirely copied in copyTextureToTexture
+- for various depth-stencil formats
+- for various copy origin and size offsets
+- for various source and destination texture sizes
+- for various source and destination mip levels
+
+Note: this is only tested for 2D textures as it is the only dimension compatible with depth-stencil.
+`
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('copyBoxOffsets', [
+ { x: 0, y: 0, width: 0, height: 0 },
+ { x: 1, y: 0, width: 0, height: 0 },
+ { x: 0, y: 1, width: 0, height: 0 },
+ { x: 0, y: 0, width: -1, height: 0 },
+ { x: 0, y: 0, width: 0, height: -1 },
+ ])
+ .combine('srcTextureSize', [
+ { width: 64, height: 64, depthOrArrayLayers: 1 },
+ { width: 64, height: 32, depthOrArrayLayers: 1 },
+ { width: 32, height: 32, depthOrArrayLayers: 1 },
+ ])
+ .combine('dstTextureSize', [
+ { width: 64, height: 64, depthOrArrayLayers: 1 },
+ { width: 64, height: 32, depthOrArrayLayers: 1 },
+ { width: 32, height: 32, depthOrArrayLayers: 1 },
+ ])
+ .combine('srcCopyLevel', [1, 2])
+ .combine('dstCopyLevel', [0, 1])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const {
+ format,
+ copyBoxOffsets,
+ srcTextureSize,
+ dstTextureSize,
+ srcCopyLevel,
+ dstCopyLevel,
+ } = t.params;
+ const kMipLevelCount = 3;
+
+ const srcTexture = t.device.createTexture({
+ size: { width: srcTextureSize.width, height: srcTextureSize.height, depthOrArrayLayers: 1 },
+ format,
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ const dstTexture = t.device.createTexture({
+ size: { width: dstTextureSize.width, height: dstTextureSize.height, depthOrArrayLayers: 1 },
+ format,
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const srcSizeAtLevel = t.GetPhysicalSubresourceSize('2d', srcTextureSize, format, srcCopyLevel);
+ const dstSizeAtLevel = t.GetPhysicalSubresourceSize('2d', dstTextureSize, format, dstCopyLevel);
+
+ const copyOrigin = { x: copyBoxOffsets.x, y: copyBoxOffsets.y, z: 0 };
+
+ const copyWidth =
+ Math.min(srcSizeAtLevel.width, dstSizeAtLevel.width) + copyBoxOffsets.width - copyOrigin.x;
+ const copyHeight =
+ Math.min(srcSizeAtLevel.height, dstSizeAtLevel.height) + copyBoxOffsets.height - copyOrigin.y;
+
+ // Depth/stencil copies must copy whole subresources.
+ const isSuccess =
+ copyOrigin.x === 0 &&
+ copyOrigin.y === 0 &&
+ copyWidth === srcSizeAtLevel.width &&
+ copyHeight === srcSizeAtLevel.height &&
+ copyWidth === dstSizeAtLevel.width &&
+ copyHeight === dstSizeAtLevel.height;
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: copyOrigin, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: copyOrigin, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: 1 },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('copy_ranges')
+ .desc(
+ `
+Test that copyTextureToTexture copy boxes must be in range of the subresource.
+- for various dimensions
+- for various offsets to a full copy for the copy origin/size
+- for various copy mip levels
+`
+ )
+ .params(u =>
+ u
+ .combine('dimension', kTextureDimensions)
+ //.beginSubcases()
+ .combine('copyBoxOffsets', [
+ { x: 0, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 1, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 1, y: 0, z: 0, width: -1, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 1, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 1, z: 0, width: 0, height: -1, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 1, width: 0, height: 1, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 2, width: 0, height: 1, depthOrArrayLayers: 0 },
+ { x: 0, y: 0, z: 0, width: 1, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: 0, height: 1, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: 1 },
+ { x: 0, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: 0 },
+ { x: 0, y: 0, z: 1, width: 0, height: 0, depthOrArrayLayers: -1 },
+ { x: 0, y: 0, z: 2, width: 0, height: 0, depthOrArrayLayers: -1 },
+ ])
+ .unless(
+ p =>
+ p.dimension === '1d' &&
+ (p.copyBoxOffsets.y !== 0 ||
+ p.copyBoxOffsets.z !== 0 ||
+ p.copyBoxOffsets.height !== 0 ||
+ p.copyBoxOffsets.depthOrArrayLayers !== 0)
+ )
+ .combine('srcCopyLevel', [0, 1, 3])
+ .combine('dstCopyLevel', [0, 1, 3])
+ .unless(p => p.dimension === '1d' && (p.srcCopyLevel !== 0 || p.dstCopyLevel !== 0))
+ )
+ .fn(async t => {
+ const { dimension, copyBoxOffsets, srcCopyLevel, dstCopyLevel } = t.params;
+
+ const textureSize = { width: 16, height: 8, depthOrArrayLayers: 3 };
+ let mipLevelCount = 4;
+ if (dimension === '1d') {
+ mipLevelCount = 1;
+ textureSize.height = 1;
+ textureSize.depthOrArrayLayers = 1;
+ }
+ const kFormat = 'rgba8unorm';
+
+ const srcTexture = t.device.createTexture({
+ size: textureSize,
+ format: kFormat,
+ dimension,
+ mipLevelCount,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ const dstTexture = t.device.createTexture({
+ size: textureSize,
+ format: kFormat,
+ dimension,
+ mipLevelCount,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const srcSizeAtLevel = t.GetPhysicalSubresourceSize(
+ dimension,
+ textureSize,
+ kFormat,
+ srcCopyLevel
+ );
+
+ const dstSizeAtLevel = t.GetPhysicalSubresourceSize(
+ dimension,
+ textureSize,
+ kFormat,
+ dstCopyLevel
+ );
+
+ const copyOrigin = { x: copyBoxOffsets.x, y: copyBoxOffsets.y, z: copyBoxOffsets.z };
+
+ const copyWidth = Math.max(
+ Math.min(srcSizeAtLevel.width, dstSizeAtLevel.width) + copyBoxOffsets.width - copyOrigin.x,
+ 0
+ );
+
+ const copyHeight = Math.max(
+ Math.min(srcSizeAtLevel.height, dstSizeAtLevel.height) + copyBoxOffsets.height - copyOrigin.y,
+ 0
+ );
+
+ const copyDepth =
+ textureSize.depthOrArrayLayers + copyBoxOffsets.depthOrArrayLayers - copyOrigin.z;
+
+ {
+ let isSuccess =
+ copyWidth <= srcSizeAtLevel.width &&
+ copyHeight <= srcSizeAtLevel.height &&
+ copyOrigin.x + copyWidth <= dstSizeAtLevel.width &&
+ copyOrigin.y + copyHeight <= dstSizeAtLevel.height;
+
+ if (dimension === '3d') {
+ isSuccess =
+ isSuccess &&
+ copyDepth <= srcSizeAtLevel.depthOrArrayLayers &&
+ copyOrigin.z + copyDepth <= dstSizeAtLevel.depthOrArrayLayers;
+ } else {
+ isSuccess =
+ isSuccess &&
+ copyDepth <= textureSize.depthOrArrayLayers &&
+ copyOrigin.z + copyDepth <= textureSize.depthOrArrayLayers;
+ }
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: copyOrigin, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ }
+
+ {
+ let isSuccess =
+ copyOrigin.x + copyWidth <= srcSizeAtLevel.width &&
+ copyOrigin.y + copyHeight <= srcSizeAtLevel.height &&
+ copyWidth <= dstSizeAtLevel.width &&
+ copyHeight <= dstSizeAtLevel.height;
+
+ if (dimension === '3d') {
+ isSuccess =
+ isSuccess &&
+ copyDepth <= dstSizeAtLevel.depthOrArrayLayers &&
+ copyOrigin.z + copyDepth <= srcSizeAtLevel.depthOrArrayLayers;
+ } else {
+ isSuccess =
+ isSuccess &&
+ copyDepth <= textureSize.depthOrArrayLayers &&
+ copyOrigin.z + copyDepth <= textureSize.depthOrArrayLayers;
+ }
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: copyOrigin, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ }
+ });
+
+g.test('copy_within_same_texture')
+ .desc(
+ `
+Test that it is an error to use copyTextureToTexture from one subresource to itself.
+- for various starting source/destination array layers.
+- for various copy sizes in number of array layers
+
+TODO: Extend to check the copy is allowed between different mip levels.
+TODO: Extend to 1D and 3D textures.`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('srcCopyOriginZ', [0, 2, 4])
+ .combine('dstCopyOriginZ', [0, 2, 4])
+ .combine('copyExtentDepth', [1, 2, 3])
+ )
+ .fn(async t => {
+ const { srcCopyOriginZ, dstCopyOriginZ, copyExtentDepth } = t.params;
+
+ const kArrayLayerCount = 7;
+
+ const testTexture = t.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: kArrayLayerCount },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const isSuccess =
+ Math.min(srcCopyOriginZ, dstCopyOriginZ) + copyExtentDepth <=
+ Math.max(srcCopyOriginZ, dstCopyOriginZ);
+ t.TestCopyTextureToTexture(
+ { texture: testTexture, origin: { x: 0, y: 0, z: srcCopyOriginZ } },
+ { texture: testTexture, origin: { x: 0, y: 0, z: dstCopyOriginZ } },
+ { width: 16, height: 16, depthOrArrayLayers: copyExtentDepth },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('copy_aspects')
+ .desc(
+ `
+Test the validations on the member 'aspect' of GPUImageCopyTexture in CopyTextureToTexture().
+- for all the color and depth-stencil formats: the texture copy aspects must be both 'all'.
+- for all the depth-only formats: the texture copy aspects must be either 'all' or 'depth-only'.
+- for all the stencil-only formats: the texture copy aspects must be either 'all' or 'stencil-only'.
+`
+ )
+ .params(u =>
+ u
+ .combine('format', ['rgba8unorm', ...kDepthStencilFormats])
+ .beginSubcases()
+ .combine('sourceAspect', ['all', 'depth-only', 'stencil-only'])
+ .combine('destinationAspect', ['all', 'depth-only', 'stencil-only'])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { format, sourceAspect, destinationAspect } = t.params;
+
+ const kTextureSize = { width: 16, height: 8, depthOrArrayLayers: 1 };
+
+ const srcTexture = t.device.createTexture({
+ size: kTextureSize,
+ format,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ const dstTexture = t.device.createTexture({
+ size: kTextureSize,
+ format,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ // MAINTENANCE_TODO: get the valid aspects from capability_info.ts.
+ const kValidAspectsForFormat = {
+ rgba8unorm: ['all'],
+
+ // kUnsizedDepthStencilFormats
+ depth24plus: ['all', 'depth-only'],
+ 'depth24plus-stencil8': ['all'],
+ 'depth32float-stencil8': ['all'],
+
+ // kSizedDepthStencilFormats
+ depth32float: ['all', 'depth-only'],
+ stencil8: ['all', 'stencil-only'],
+ depth16unorm: ['all', 'depth-only'],
+ };
+
+ const isSourceAspectValid = kValidAspectsForFormat[format].includes(sourceAspect);
+ const isDestinationAspectValid = kValidAspectsForFormat[format].includes(destinationAspect);
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: { x: 0, y: 0, z: 0 }, aspect: sourceAspect },
+ { texture: dstTexture, origin: { x: 0, y: 0, z: 0 }, aspect: destinationAspect },
+ kTextureSize,
+ isSourceAspectValid && isDestinationAspectValid ? 'Success' : 'FinishError'
+ );
+ });
+
+g.test('copy_ranges_with_compressed_texture_formats')
+ .desc(
+ `
+Test that copyTextureToTexture copy boxes must be in range of the subresource and aligned to the block size
+- for various dimensions
+- for various offsets to a full copy for the copy origin/size
+- for various copy mip levels
+
+TODO: Express the offsets in "block size" so as to be able to test non-4x4 compressed formats
+`
+ )
+ .params(u =>
+ u
+ .combine('format', kCompressedTextureFormats)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('copyBoxOffsets', [
+ { x: 0, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 1, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 4, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: -1, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: -4, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 1, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 4, z: 0, width: 0, height: 0, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: 0, height: -1, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: 0, height: -4, depthOrArrayLayers: -2 },
+ { x: 0, y: 0, z: 0, width: 0, height: 0, depthOrArrayLayers: 0 },
+ { x: 0, y: 0, z: 1, width: 0, height: 0, depthOrArrayLayers: -1 },
+ ])
+ .combine('srcCopyLevel', [0, 1, 2])
+ .combine('dstCopyLevel', [0, 1, 2])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { format, dimension, copyBoxOffsets, srcCopyLevel, dstCopyLevel } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+
+ const kTextureSize = {
+ width: 15 * blockWidth,
+ height: 12 * blockHeight,
+ depthOrArrayLayers: 3,
+ };
+ const kMipLevelCount = 4;
+
+ const srcTexture = t.device.createTexture({
+ size: kTextureSize,
+ format,
+ dimension,
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ const dstTexture = t.device.createTexture({
+ size: kTextureSize,
+ format,
+ dimension,
+ mipLevelCount: kMipLevelCount,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const srcSizeAtLevel = t.GetPhysicalSubresourceSize(
+ dimension,
+ kTextureSize,
+ format,
+ srcCopyLevel
+ );
+
+ const dstSizeAtLevel = t.GetPhysicalSubresourceSize(
+ dimension,
+ kTextureSize,
+ format,
+ dstCopyLevel
+ );
+
+ const copyOrigin = { x: copyBoxOffsets.x, y: copyBoxOffsets.y, z: copyBoxOffsets.z };
+
+ const copyWidth = Math.max(
+ Math.min(srcSizeAtLevel.width, dstSizeAtLevel.width) + copyBoxOffsets.width - copyOrigin.x,
+ 0
+ );
+
+ const copyHeight = Math.max(
+ Math.min(srcSizeAtLevel.height, dstSizeAtLevel.height) + copyBoxOffsets.height - copyOrigin.y,
+ 0
+ );
+
+ const copyDepth =
+ kTextureSize.depthOrArrayLayers + copyBoxOffsets.depthOrArrayLayers - copyOrigin.z;
+
+ const texelBlockWidth = kTextureFormatInfo[format].blockWidth;
+ const texelBlockHeight = kTextureFormatInfo[format].blockHeight;
+
+ const isSuccessForCompressedFormats =
+ copyOrigin.x % texelBlockWidth === 0 &&
+ copyOrigin.y % texelBlockHeight === 0 &&
+ copyWidth % texelBlockWidth === 0 &&
+ copyHeight % texelBlockHeight === 0;
+
+ {
+ const isSuccess =
+ isSuccessForCompressedFormats &&
+ copyWidth <= srcSizeAtLevel.width &&
+ copyHeight <= srcSizeAtLevel.height &&
+ copyOrigin.x + copyWidth <= dstSizeAtLevel.width &&
+ copyOrigin.y + copyHeight <= dstSizeAtLevel.height &&
+ copyOrigin.z + copyDepth <= kTextureSize.depthOrArrayLayers;
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: copyOrigin, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ }
+
+ {
+ const isSuccess =
+ isSuccessForCompressedFormats &&
+ copyOrigin.x + copyWidth <= srcSizeAtLevel.width &&
+ copyOrigin.y + copyHeight <= srcSizeAtLevel.height &&
+ copyWidth <= dstSizeAtLevel.width &&
+ copyHeight <= dstSizeAtLevel.height &&
+ copyOrigin.z + copyDepth <= kTextureSize.depthOrArrayLayers;
+
+ t.TestCopyTextureToTexture(
+ { texture: srcTexture, origin: copyOrigin, mipLevel: srcCopyLevel },
+ { texture: dstTexture, origin: { x: 0, y: 0, z: 0 }, mipLevel: dstCopyLevel },
+ { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth },
+ isSuccess ? 'Success' : 'FinishError'
+ );
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/debug.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/debug.spec.js
new file mode 100644
index 0000000000..467cbb223e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/debug.spec.js
@@ -0,0 +1,65 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API validation test for debug groups and markers
+
+Test Coverage:
+ - For each encoder type (GPUCommandEncoder, GPUComputeEncoder, GPURenderPassEncoder,
+ GPURenderBundleEncoder):
+ - Test that all pushDebugGroup must have a corresponding popDebugGroup
+ - Push and pop counts of 0, 1, and 2 will be used.
+ - An error must be generated for non matching counts.
+ - Test calling pushDebugGroup with empty and non-empty strings.
+ - Test inserting a debug marker with empty and non-empty strings.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { kEncoderTypes } from '../../../../util/command_buffer_maker.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('debug_group_balanced')
+ .params(u =>
+ u
+ .combine('encoderType', kEncoderTypes)
+ .beginSubcases()
+ .combine('pushCount', [0, 1, 2])
+ .combine('popCount', [0, 1, 2])
+ )
+ .fn(t => {
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(t.params.encoderType);
+ for (let i = 0; i < t.params.pushCount; ++i) {
+ encoder.pushDebugGroup(`${i}`);
+ }
+ for (let i = 0; i < t.params.popCount; ++i) {
+ encoder.popDebugGroup();
+ }
+ validateFinishAndSubmit(t.params.pushCount === t.params.popCount, true);
+ });
+
+g.test('debug_group')
+ .params(u =>
+ u //
+ .combine('encoderType', kEncoderTypes)
+ .beginSubcases()
+ .combine('label', ['', 'group'])
+ )
+ .fn(t => {
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(t.params.encoderType);
+ encoder.pushDebugGroup(t.params.label);
+ encoder.popDebugGroup();
+ validateFinishAndSubmit(true, true);
+ });
+
+g.test('debug_marker')
+ .params(u =>
+ u //
+ .combine('encoderType', kEncoderTypes)
+ .beginSubcases()
+ .combine('label', ['', 'marker'])
+ )
+ .fn(t => {
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(t.params.encoderType);
+ encoder.insertDebugMarker(t.params.label);
+ validateFinishAndSubmit(true, true);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/index_access.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/index_access.spec.js
new file mode 100644
index 0000000000..1aa7ff1c12
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/index_access.spec.js
@@ -0,0 +1,163 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for indexed draws accessing the index buffer.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ createIndexBuffer(indexData) {
+ return this.makeBufferWithContents(new Uint32Array(indexData), GPUBufferUsage.INDEX);
+ }
+
+ createRenderPipeline() {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: {
+ topology: 'triangle-strip',
+ stripIndexFormat: 'uint32',
+ },
+ });
+ }
+
+ beginRenderPass(encoder) {
+ const colorAttachment = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ return encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+
+ drawIndexed(
+ indexBuffer,
+ indexCount,
+ instanceCount,
+ firstIndex,
+ baseVertex,
+ firstInstance,
+ isSuccess
+ ) {
+ const pipeline = this.createRenderPipeline();
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = this.beginRenderPass(encoder);
+ pass.setPipeline(pipeline);
+ pass.setIndexBuffer(indexBuffer, 'uint32');
+ pass.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
+ pass.end();
+
+ if (isSuccess) {
+ this.device.queue.submit([encoder.finish()]);
+ } else {
+ this.expectValidationError(() => {
+ encoder.finish();
+ });
+ }
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('out_of_bounds')
+ .desc(
+ `Test drawing with out of bound index access to make sure encoder validation catch the
+ following indexCount and firstIndex OOB conditions
+ - either is within bound but indexCount + firstIndex is out of bound
+ - only firstIndex is out of bound
+ - only indexCount is out of bound
+ - firstIndex much larger than indexCount
+ - indexCount much larger than firstIndex
+ - max uint32 value for both to make sure the sum doesn't overflow
+ - max uint32 indexCount and small firstIndex
+ - max uint32 firstIndex and small indexCount
+ Together with normal and large instanceCount`
+ )
+ .params(
+ u =>
+ u
+ .combineWithParams([
+ { indexCount: 6, firstIndex: 0 }, // draw all 6 out of 6 index
+ { indexCount: 5, firstIndex: 1 }, // draw the last 5 out of 6 index
+ { indexCount: 1, firstIndex: 5 }, // draw the last 1 out of 6 index
+ { indexCount: 0, firstIndex: 6 }, // firstIndex point to the one after last, but (indexCount + firstIndex) * stride <= bufferSize, valid
+ { indexCount: 0, firstIndex: 7 }, // (indexCount + firstIndex) * stride > bufferSize, invalid
+ { indexCount: 7, firstIndex: 0 }, // only indexCount out of bound
+ { indexCount: 6, firstIndex: 1 }, // indexCount + firstIndex out of bound
+ { indexCount: 1, firstIndex: 6 }, // indexCount valid, but (indexCount + firstIndex) out of bound
+ { indexCount: 6, firstIndex: 10000 }, // firstIndex much larger than the bound
+ { indexCount: 10000, firstIndex: 0 }, // indexCount much larger than the bound
+ { indexCount: 0xffffffff, firstIndex: 0xffffffff }, // max uint32 value
+ { indexCount: 0xffffffff, firstIndex: 2 }, // max uint32 indexCount and small firstIndex
+ { indexCount: 2, firstIndex: 0xffffffff }, // small indexCount and max uint32 firstIndex
+ ])
+ .combine('instanceCount', [1, 10000]) // normal and large instanceCount
+ )
+ .fn(t => {
+ const { indexCount, firstIndex, instanceCount } = t.params;
+
+ const indexBuffer = t.createIndexBuffer([0, 1, 2, 3, 1, 2]);
+ const isSuccess = indexCount + firstIndex <= 6;
+
+ t.drawIndexed(indexBuffer, indexCount, instanceCount, firstIndex, 0, 0, isSuccess);
+ });
+
+g.test('out_of_bounds_zero_sized_index_buffer')
+ .desc(
+ `Test drawing with an empty index buffer to make sure the encoder validation catch the
+ following indexCount and firstIndex conditions
+ - indexCount + firstIndex is out of bound
+ - indexCount is 0 but firstIndex is out of bound
+ - only indexCount is out of bound
+ - both are 0s (not out of bound) but index buffer size is 0
+ Together with normal and large instanceCount`
+ )
+ .params(
+ u =>
+ u
+ .combineWithParams([
+ { indexCount: 3, firstIndex: 1 }, // indexCount + firstIndex out of bound
+ { indexCount: 0, firstIndex: 1 }, // indexCount is 0 but firstIndex out of bound
+ { indexCount: 3, firstIndex: 0 }, // only indexCount out of bound
+ { indexCount: 0, firstIndex: 0 }, // just zeros, valid
+ ])
+ .combine('instanceCount', [1, 10000]) // normal and large instanceCount
+ )
+ .fn(t => {
+ const { indexCount, firstIndex, instanceCount } = t.params;
+
+ const indexBuffer = t.createIndexBuffer([]);
+ const isSuccess = indexCount + firstIndex <= 0;
+
+ t.drawIndexed(indexBuffer, indexCount, instanceCount, firstIndex, 0, 0, isSuccess);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/draw.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/draw.spec.js
new file mode 100644
index 0000000000..6a3733a5eb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/draw.spec.js
@@ -0,0 +1,827 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Here we test the validation for draw functions, mainly the buffer access validation. All four types
+of draw calls are tested, and test that validation errors do / don't occur for certain call type
+and parameters as expect.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { kVertexFormatInfo } from '../../../../../capability_info.js';
+
+import { ValidationTest } from '../../../validation_test.js';
+
+function callDrawIndexed(test, encoder, drawType, param) {
+ switch (drawType) {
+ case 'drawIndexed': {
+ encoder.drawIndexed(
+ param.indexCount,
+ param.instanceCount ?? 1,
+ param.firstIndex ?? 0,
+ param.baseVertex ?? 0,
+ param.firstInstance ?? 0
+ );
+
+ break;
+ }
+ case 'drawIndexedIndirect': {
+ const indirectArray = new Int32Array([
+ param.indexCount,
+ param.instanceCount ?? 1,
+ param.firstIndex ?? 0,
+ param.baseVertex ?? 0,
+ param.firstInstance ?? 0,
+ ]);
+
+ const indirectBuffer = test.makeBufferWithContents(indirectArray, GPUBufferUsage.INDIRECT);
+ encoder.drawIndexedIndirect(indirectBuffer, 0);
+ break;
+ }
+ }
+}
+
+function callDraw(test, encoder, drawType, param) {
+ switch (drawType) {
+ case 'draw': {
+ encoder.draw(
+ param.vertexCount,
+ param.instanceCount ?? 1,
+ param.firstVertex ?? 0,
+ param.firstInstance ?? 0
+ );
+
+ break;
+ }
+ case 'drawIndirect': {
+ const indirectArray = new Int32Array([
+ param.vertexCount,
+ param.instanceCount ?? 1,
+ param.firstVertex ?? 0,
+ param.firstInstance ?? 0,
+ ]);
+
+ const indirectBuffer = test.makeBufferWithContents(indirectArray, GPUBufferUsage.INDIRECT);
+ encoder.drawIndirect(indirectBuffer, 0);
+ break;
+ }
+ }
+}
+
+function makeTestPipeline(test, buffers) {
+ const bufferLayouts = [];
+ for (const b of buffers) {
+ bufferLayouts[b.slot] = b;
+ }
+
+ return test.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: test.device.createShaderModule({
+ code: test.getNoOpShaderCode('VERTEX'),
+ }),
+ entryPoint: 'main',
+ buffers: bufferLayouts,
+ },
+ fragment: {
+ module: test.device.createShaderModule({
+ code: test.getNoOpShaderCode('FRAGMENT'),
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+}
+
+function makeTestPipelineWithVertexAndInstanceBuffer(
+ test,
+ arrayStride,
+ attributeFormat,
+ attributeOffset = 0
+) {
+ const vertexBufferLayouts = [
+ {
+ slot: 1,
+ stepMode: 'vertex',
+ arrayStride,
+ attributes: [
+ {
+ shaderLocation: 2,
+ format: attributeFormat,
+ offset: attributeOffset,
+ },
+ ],
+ },
+ {
+ slot: 7,
+ stepMode: 'instance',
+ arrayStride,
+ attributes: [
+ {
+ shaderLocation: 6,
+ format: attributeFormat,
+ offset: attributeOffset,
+ },
+ ],
+ },
+ ];
+
+ return makeTestPipeline(test, vertexBufferLayouts);
+}
+
+// Default parameters for all kind of draw call, arbitrary non-zero values that is not very large.
+const kDefaultParameterForDraw = {
+ instanceCount: 100,
+ firstInstance: 100,
+};
+
+// Default parameters for non-indexed draw, arbitrary non-zero values that is not very large.
+const kDefaultParameterForNonIndexedDraw = {
+ vertexCount: 100,
+ firstVertex: 100,
+};
+
+// Default parameters for indexed draw call and required index buffer, arbitrary non-zero values
+// that is not very large.
+const kDefaultParameterForIndexedDraw = {
+ indexCount: 100,
+ firstIndex: 100,
+ baseVertex: 100,
+ indexFormat: 'uint16',
+ indexBufferSize: 2 * 200, // exact required bound size for index buffer
+};
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test(`unused_buffer_bound`)
+ .desc(
+ `
+In this test we test that a small buffer bound to unused buffer slot won't cause validation error.
+- All draw commands,
+ - An unused {index , vertex} buffer with uselessly small range is bound (immediately before draw
+ call)
+`
+ )
+ .params(u =>
+ u //
+ .combine('smallIndexBuffer', [false, true])
+ .combine('smallVertexBuffer', [false, true])
+ .combine('smallInstanceBuffer', [false, true])
+ .beginSubcases()
+ .combine('drawType', ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect'])
+ .unless(
+ // Always provide index buffer of enough size if it is used by indexed draw
+ p =>
+ p.smallIndexBuffer &&
+ (p.drawType === 'drawIndexed' || p.drawType === 'drawIndexedIndirect')
+ )
+ .combine('bufferOffset', [0, 4])
+ .combine('boundSize', [0, 1])
+ )
+ .fn(async t => {
+ const {
+ smallIndexBuffer,
+ smallVertexBuffer,
+ smallInstanceBuffer,
+ drawType,
+ bufferOffset,
+ boundSize,
+ } = t.params;
+ const renderPipeline = t.createNoOpRenderPipeline();
+ const bufferSize = bufferOffset + boundSize;
+ const smallBuffer = t.createBufferWithState('valid', {
+ size: bufferSize,
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.VERTEX,
+ });
+
+ // An index buffer of enough size, used if smallIndexBuffer === false
+ const { indexFormat, indexBufferSize } = kDefaultParameterForIndexedDraw;
+ const indexBuffer = t.createBufferWithState('valid', {
+ size: indexBufferSize,
+ usage: GPUBufferUsage.INDEX,
+ });
+
+ for (const encoderType of ['render bundle', 'render pass']) {
+ for (const setPipelineBeforeBuffer of [false, true]) {
+ const commandBufferMaker = t.createEncoder(encoderType);
+ const renderEncoder = commandBufferMaker.encoder;
+
+ if (setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+
+ if (drawType === 'drawIndexed' || drawType === 'drawIndexedIndirect') {
+ // Always use large enough index buffer for indexed draw. Index buffer OOB validation is
+ // tested in index_buffer_OOB.
+ renderEncoder.setIndexBuffer(indexBuffer, indexFormat, 0, indexBufferSize);
+ } else if (smallIndexBuffer) {
+ renderEncoder.setIndexBuffer(smallBuffer, indexFormat, bufferOffset, boundSize);
+ }
+ if (smallVertexBuffer) {
+ renderEncoder.setVertexBuffer(1, smallBuffer, bufferOffset, boundSize);
+ }
+ if (smallInstanceBuffer) {
+ renderEncoder.setVertexBuffer(7, smallBuffer, bufferOffset, boundSize);
+ }
+
+ if (!setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+
+ if (drawType === 'draw' || drawType === 'drawIndirect') {
+ const drawParam = {
+ ...kDefaultParameterForDraw,
+ ...kDefaultParameterForNonIndexedDraw,
+ };
+ callDraw(t, renderEncoder, drawType, drawParam);
+ } else {
+ const drawParam = {
+ ...kDefaultParameterForDraw,
+ ...kDefaultParameterForIndexedDraw,
+ };
+ callDrawIndexed(t, renderEncoder, drawType, drawParam);
+ }
+
+ // Binding a unused small index/vertex buffer will never cause validation error.
+ commandBufferMaker.validateFinishAndSubmit(true, true);
+ }
+ }
+ });
+
+g.test(`index_buffer_OOB`)
+ .desc(
+ `
+In this test we test that index buffer OOB is caught as a validation error in drawIndexed, but not in
+drawIndexedIndirect as it is GPU-validated.
+- Issue an indexed draw call, with the following index buffer states, for {all index formats}:
+ - range and GPUBuffer are exactly the required size for the draw call
+ - range is too small but GPUBuffer is still large enough
+ - range and GPUBuffer are both too small
+`
+ )
+ .params(u =>
+ u
+ .combine('bufferSizeInElements', [10, 100])
+ // Binding size is always no larger than buffer size, make sure that setIndexBuffer succeed
+ .combine('bindingSizeInElements', [10])
+ .combine('drawIndexCount', [10, 11])
+ .combine('drawType', ['drawIndexed', 'drawIndexedIndirect'])
+ .beginSubcases()
+ .combine('indexFormat', ['uint16', 'uint32'])
+ )
+ .fn(async t => {
+ const {
+ indexFormat,
+ bindingSizeInElements,
+ bufferSizeInElements,
+ drawIndexCount,
+ drawType,
+ } = t.params;
+
+ const indexElementSize = indexFormat === 'uint16' ? 2 : 4;
+ const bindingSize = bindingSizeInElements * indexElementSize;
+ const bufferSize = bufferSizeInElements * indexElementSize;
+
+ const desc = {
+ size: bufferSize,
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
+ };
+ const indexBuffer = t.createBufferWithState('valid', desc);
+
+ const drawCallParam = {
+ indexCount: drawIndexCount,
+ };
+
+ // Encoder finish will succeed if no index buffer access OOB when calling drawIndexed,
+ // and always succeed when calling drawIndexedIndirect.
+ const isFinishSuccess =
+ drawIndexCount <= bindingSizeInElements || drawType === 'drawIndexedIndirect';
+
+ const renderPipeline = t.createNoOpRenderPipeline();
+
+ for (const encoderType of ['render bundle', 'render pass']) {
+ for (const setPipelineBeforeBuffer of [false, true]) {
+ const commandBufferMaker = t.createEncoder(encoderType);
+ const renderEncoder = commandBufferMaker.encoder;
+
+ if (setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+ renderEncoder.setIndexBuffer(indexBuffer, indexFormat, 0, bindingSize);
+ if (!setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+
+ callDrawIndexed(t, renderEncoder, drawType, drawCallParam);
+
+ commandBufferMaker.validateFinishAndSubmit(isFinishSuccess, true);
+ }
+ }
+ });
+
+g.test(`vertex_buffer_OOB`)
+ .desc(
+ `
+In this test we test the vertex buffer OOB validation in draw calls. Specifically, only vertex step
+mode buffer OOB in draw and instance step mode buffer OOB in draw and drawIndexed are CPU-validated.
+Other cases are handled by robust access and no validation error occurs.
+- Test that:
+ - Draw call needs to read {=, >} any bound vertex buffer range, with GPUBuffer that is {large
+ enough, exactly the size of bound range}
+ - Binding size = 0 (ensure it's not treated as a special case)
+ - x= weird buffer offset values
+ - x= weird attribute offset values
+ - x= weird arrayStride values
+ - x= {render pass, render bundle}
+- For vertex step mode vertex buffer,
+ - Test that:
+ - vertexCount largeish
+ - firstVertex {=, >} 0
+ - arrayStride is 0 and bound buffer size too small
+ - (vertexCount + firstVertex) is zero
+ - Validation error occurs in:
+ - draw
+ - drawIndexed with a zero array stride vertex step mode buffer OOB
+ - Otherwise no validation error in drawIndexed, draIndirect and drawIndexedIndirect
+- For instance step mode vertex buffer,
+ - Test with draw and drawIndexed:
+ - instanceCount largeish
+ - firstInstance {=, >} 0
+ - arrayStride is 0 and bound buffer size too small
+ - (instanceCount + firstInstance) is zero
+ - Validation error occurs in draw and drawIndexed
+ - No validation error in drawIndirect and drawIndexedIndirect
+
+In this test, we use a a render pipeline requiring one vertex step mode with different vertex buffer
+layouts (attribute offset, array stride, vertex format). Then for a given drawing parameter set (e.g.,
+vertexCount, instanceCount, firstVertex, indexCount), we calculate the exactly required size for
+vertex step mode vertex buffer. Then, we generate buffer parameters (i.e. GPU buffer size,
+binding offset and binding size) for all buffers, covering both (bound size == required size),
+(bound size == required size - 1), and (bound size == 0), and test that draw and drawIndexed will
+success/error as expected. Such set of buffer parameters should include cases like weird offset values.
+`
+ )
+ .params(u =>
+ u
+ // type of draw call
+ .combine('type', ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect'])
+ // the state of vertex step mode vertex buffer bound size
+ .combine('VBSize', ['zero', 'exile', 'enough'])
+ // the state of instance step mode vertex buffer bound size
+ .combine('IBSize', ['zero', 'exile', 'enough'])
+ // should the vertex stride count be zero
+ .combine('VStride0', [false, true])
+ // should the instance stride count be zero
+ .combine('IStride0', [false, true])
+ // the state of array stride
+ .combine('AStride', ['zero', 'exact', 'oversize'])
+ // the factor for offset of attributes in vertex layout
+ .combine('offset', [0, 1, 2, 7]) // the offset of attribute will be factor * MIN(4, sizeof(vertexFormat))
+ .beginSubcases()
+ .combine('setBufferOffset', [0, 200]) // must be a multiple of 4
+ .combine('attributeFormat', ['snorm8x2', 'float32', 'float16x4'])
+ .combine('vertexCount', [0, 1, 10000])
+ .combine('firstVertex', [0, 10000])
+ .filter(p => p.VStride0 === (p.firstVertex + p.vertexCount === 0))
+ .combine('instanceCount', [0, 1, 10000])
+ .combine('firstInstance', [0, 10000])
+ .filter(p => p.IStride0 === (p.firstInstance + p.instanceCount === 0))
+ .unless(p => p.vertexCount === 10000 && p.instanceCount === 10000)
+ )
+ .fn(async t => {
+ const {
+ type: drawType,
+ VBSize: boundVertexBufferSizeState,
+ IBSize: boundInstanceBufferSizeState,
+ VStride0: zeroVertexStrideCount,
+ IStride0: zeroInstanceStrideCount,
+ AStride: arrayStrideState,
+ offset: attributeOffsetFactor,
+ setBufferOffset,
+ attributeFormat,
+ vertexCount,
+ instanceCount,
+ firstVertex,
+ firstInstance,
+ } = t.params;
+
+ const attributeFormatInfo = kVertexFormatInfo[attributeFormat];
+ const formatSize = attributeFormatInfo.bytesPerComponent * attributeFormatInfo.componentCount;
+ const attributeOffset = attributeOffsetFactor * Math.min(4, formatSize);
+ const lastStride = attributeOffset + formatSize;
+ let arrayStride = 0;
+ if (arrayStrideState !== 'zero') {
+ arrayStride = lastStride;
+ if (arrayStrideState === 'oversize') {
+ // Add an arbitrary number to array stride to make it larger than required by attributes
+ arrayStride = arrayStride + 20;
+ }
+ arrayStride = arrayStride + (-arrayStride & 3); // Make sure arrayStride is a multiple of 4
+ }
+
+ const calcSetBufferSize = (boundBufferSizeState, strideCount) => {
+ let requiredBufferSize;
+ if (strideCount > 0) {
+ requiredBufferSize = arrayStride * (strideCount - 1) + lastStride;
+ } else {
+ // Spec do not validate bounded buffer size if strideCount == 0.
+ requiredBufferSize = lastStride;
+ }
+ let setBufferSize;
+ switch (boundBufferSizeState) {
+ case 'zero': {
+ setBufferSize = 0;
+ break;
+ }
+ case 'exile': {
+ setBufferSize = requiredBufferSize - 1;
+ break;
+ }
+ case 'enough': {
+ setBufferSize = requiredBufferSize;
+ break;
+ }
+ }
+
+ return setBufferSize;
+ };
+
+ const strideCountForVertexBuffer = firstVertex + vertexCount;
+ const setVertexBufferSize = calcSetBufferSize(
+ boundVertexBufferSizeState,
+ strideCountForVertexBuffer
+ );
+
+ const vertexBufferSize = setBufferOffset + setVertexBufferSize;
+ const strideCountForInstanceBuffer = firstInstance + instanceCount;
+ const setInstanceBufferSize = calcSetBufferSize(
+ boundInstanceBufferSizeState,
+ strideCountForInstanceBuffer
+ );
+
+ const instanceBufferSize = setBufferOffset + setInstanceBufferSize;
+
+ const vertexBuffer = t.createBufferWithState('valid', {
+ size: vertexBufferSize,
+ usage: GPUBufferUsage.VERTEX,
+ });
+ const instanceBuffer = t.createBufferWithState('valid', {
+ size: instanceBufferSize,
+ usage: GPUBufferUsage.VERTEX,
+ });
+
+ const renderPipeline = makeTestPipelineWithVertexAndInstanceBuffer(
+ t,
+ arrayStride,
+ attributeFormat,
+ attributeOffset
+ );
+
+ for (const encoderType of ['render bundle', 'render pass']) {
+ for (const setPipelineBeforeBuffer of [false, true]) {
+ const commandBufferMaker = t.createEncoder(encoderType);
+ const renderEncoder = commandBufferMaker.encoder;
+
+ if (setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+ renderEncoder.setVertexBuffer(1, vertexBuffer, setBufferOffset, setVertexBufferSize);
+ renderEncoder.setVertexBuffer(7, instanceBuffer, setBufferOffset, setInstanceBufferSize);
+ if (!setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+
+ if (drawType === 'draw' || drawType === 'drawIndirect') {
+ const drawParam = {
+ vertexCount,
+ instanceCount,
+ firstVertex,
+ firstInstance,
+ };
+
+ callDraw(t, renderEncoder, drawType, drawParam);
+ } else {
+ const {
+ indexFormat,
+ indexCount,
+ firstIndex,
+ indexBufferSize,
+ } = kDefaultParameterForIndexedDraw;
+
+ const desc = {
+ size: indexBufferSize,
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
+ };
+ const indexBuffer = t.createBufferWithState('valid', desc);
+
+ const drawParam = {
+ indexCount,
+ instanceCount,
+ firstIndex,
+ baseVertex: firstVertex,
+ firstInstance,
+ };
+
+ renderEncoder.setIndexBuffer(indexBuffer, indexFormat, 0, indexBufferSize);
+ callDrawIndexed(t, renderEncoder, drawType, drawParam);
+ }
+
+ const isVertexBufferOOB =
+ boundVertexBufferSizeState !== 'enough' &&
+ drawType === 'draw' && // drawIndirect, drawIndexed, and drawIndexedIndirect do not validate vertex step mode buffer
+ !zeroVertexStrideCount; // vertex step mode buffer never OOB if stride count = 0
+ const isInstanceBufferOOB =
+ boundInstanceBufferSizeState !== 'enough' &&
+ (drawType === 'draw' || drawType === 'drawIndexed') && // drawIndirect and drawIndexedIndirect do not validate instance step mode buffer
+ !zeroInstanceStrideCount; // vertex step mode buffer never OOB if stride count = 0
+ const isFinishSuccess = !isVertexBufferOOB && !isInstanceBufferOOB;
+
+ commandBufferMaker.validateFinishAndSubmit(isFinishSuccess, true);
+ }
+ }
+ });
+
+g.test(`buffer_binding_overlap`)
+ .desc(
+ `
+In this test we test that binding one GPU buffer to multiple vertex buffer slot or both vertex
+buffer slot and index buffer will cause no validation error, with completely/partial overlap.
+ - x= all draw types
+`
+ )
+ .params(u =>
+ u //
+ .combine('drawType', ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect'])
+ .beginSubcases()
+ .combine('vertexBoundOffestFactor', [0, 0.5, 1, 1.5, 2])
+ .combine('instanceBoundOffestFactor', [0, 0.5, 1, 1.5, 2])
+ .combine('indexBoundOffestFactor', [0, 0.5, 1, 1.5, 2])
+ .combine('arrayStrideState', ['zero', 'exact', 'oversize'])
+ )
+ .fn(async t => {
+ const {
+ drawType,
+ vertexBoundOffestFactor,
+ instanceBoundOffestFactor,
+ indexBoundOffestFactor,
+ arrayStrideState,
+ } = t.params;
+
+ // Compute the array stride for vertex step mode and instance step mode attribute
+ const attributeFormat = 'float32x4';
+ const attributeFormatInfo = kVertexFormatInfo[attributeFormat];
+ const formatSize = attributeFormatInfo.bytesPerComponent * attributeFormatInfo.componentCount;
+ const attributeOffset = 0;
+ const lastStride = attributeOffset + formatSize;
+ let arrayStride = 0;
+ if (arrayStrideState !== 'zero') {
+ arrayStride = lastStride;
+ if (arrayStrideState === 'oversize') {
+ // Add an arbitrary number to array stride
+ arrayStride = arrayStride + 20;
+ }
+ arrayStride = arrayStride + (-arrayStride & 3); // Make sure arrayStride is a multiple of 4
+ }
+
+ const calcAttributeBufferSize = strideCount => {
+ let requiredBufferSize;
+ if (strideCount > 0) {
+ requiredBufferSize = arrayStride * (strideCount - 1) + lastStride;
+ } else {
+ // Spec do not validate bounded buffer size if strideCount == 0.
+ requiredBufferSize = lastStride;
+ }
+ return requiredBufferSize;
+ };
+
+ const calcSetBufferOffset = (requiredSetBufferSize, offsetFactor) => {
+ const offset = Math.ceil(requiredSetBufferSize * offsetFactor);
+ const alignedOffset = offset + (-offset & 3); // Make sure offset is a multiple of 4
+ return alignedOffset;
+ };
+
+ // Compute required bound range for all vertex and index buffer to ensure the shared GPU buffer
+ // has enough size.
+ const { vertexCount, firstVertex } = kDefaultParameterForNonIndexedDraw;
+ const strideCountForVertexBuffer = firstVertex + vertexCount;
+ const setVertexBufferSize = calcAttributeBufferSize(strideCountForVertexBuffer);
+ const setVertexBufferOffset = calcSetBufferOffset(setVertexBufferSize, vertexBoundOffestFactor);
+ let requiredBufferSize = setVertexBufferOffset + setVertexBufferSize;
+
+ const { instanceCount, firstInstance } = kDefaultParameterForDraw;
+ const strideCountForInstanceBuffer = firstInstance + instanceCount;
+ const setInstanceBufferSize = calcAttributeBufferSize(strideCountForInstanceBuffer);
+ const setInstanceBufferOffset = calcSetBufferOffset(
+ setInstanceBufferSize,
+ instanceBoundOffestFactor
+ );
+
+ requiredBufferSize = Math.max(
+ requiredBufferSize,
+ setInstanceBufferOffset + setInstanceBufferSize
+ );
+
+ const { indexBufferSize: setIndexBufferSize, indexFormat } = kDefaultParameterForIndexedDraw;
+ const setIndexBufferOffset = calcSetBufferOffset(setIndexBufferSize, indexBoundOffestFactor);
+ requiredBufferSize = Math.max(requiredBufferSize, setIndexBufferOffset + setIndexBufferSize);
+
+ // Create the shared GPU buffer with both vertetx and index usage
+ const sharedBuffer = t.createBufferWithState('valid', {
+ size: requiredBufferSize,
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.INDEX,
+ });
+
+ const renderPipeline = makeTestPipelineWithVertexAndInstanceBuffer(
+ t,
+ arrayStride,
+ attributeFormat
+ );
+
+ for (const encoderType of ['render bundle', 'render pass']) {
+ for (const setPipelineBeforeBuffer of [false, true]) {
+ const commandBufferMaker = t.createEncoder(encoderType);
+ const renderEncoder = commandBufferMaker.encoder;
+
+ if (setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+ renderEncoder.setVertexBuffer(1, sharedBuffer, setVertexBufferOffset, setVertexBufferSize);
+ renderEncoder.setVertexBuffer(
+ 7,
+ sharedBuffer,
+ setInstanceBufferOffset,
+ setInstanceBufferSize
+ );
+
+ renderEncoder.setIndexBuffer(
+ sharedBuffer,
+ indexFormat,
+ setIndexBufferOffset,
+ setIndexBufferSize
+ );
+
+ if (!setPipelineBeforeBuffer) {
+ renderEncoder.setPipeline(renderPipeline);
+ }
+
+ if (drawType === 'draw' || drawType === 'drawIndirect') {
+ const drawParam = {
+ ...kDefaultParameterForDraw,
+ ...kDefaultParameterForNonIndexedDraw,
+ };
+ callDraw(t, renderEncoder, drawType, drawParam);
+ } else {
+ const drawParam = {
+ ...kDefaultParameterForDraw,
+ ...kDefaultParameterForIndexedDraw,
+ };
+ callDrawIndexed(t, renderEncoder, drawType, drawParam);
+ }
+
+ // Since all bound buffer are of enough size, draw call should always succeed.
+ commandBufferMaker.validateFinishAndSubmit(true, true);
+ }
+ }
+ });
+
+g.test(`last_buffer_setting_take_account`)
+ .desc(
+ `
+In this test we test that only the last setting for a buffer slot take account.
+- All (non/indexed, in/direct) draw commands
+ - setPl, setVB, setIB, draw, {setPl,setVB,setIB,nothing (control)}, then a larger draw that
+ wouldn't have been valid before that
+`
+ )
+ .unimplemented();
+
+g.test(`max_draw_count`)
+ .desc(
+ `
+In this test we test that draw count which exceeds
+GPURenderPassDescriptor.maxDrawCount causes validation error on
+GPUCommandEncoder.finish(). The test sets specified maxDrawCount,
+calls specified draw call specified times with or without bundles,
+and checks whether GPUCommandEncoder.finish() causes a validation error.
+ - x= whether to use a bundle for the first half of the draw calls
+ - x= whether to use a bundle for the second half of the draw calls
+ - x= several different draw counts
+ - x= several different maxDrawCounts
+`
+ )
+ .params(u =>
+ u
+ .combine('bundleFirstHalf', [false, true])
+ .combine('bundleSecondHalf', [false, true])
+ .combine('maxDrawCount', [0, 1, 4, 16])
+ .beginSubcases()
+ .expand('drawCount', p => new Set([0, p.maxDrawCount, p.maxDrawCount + 1]))
+ )
+ .fn(async t => {
+ const { bundleFirstHalf, bundleSecondHalf, maxDrawCount, drawCount } = t.params;
+
+ const colorFormat = 'rgba8unorm';
+ const colorTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: colorFormat,
+ mipLevelCount: 1,
+ sampleCount: 1,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() {}`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: colorFormat, writeMask: 0 }],
+ },
+ });
+
+ const indexBuffer = t.makeBufferWithContents(new Uint16Array([0, 0, 0]), GPUBufferUsage.INDEX);
+ const indirectBuffer = t.makeBufferWithContents(
+ new Uint32Array([3, 1, 0, 0]),
+ GPUBufferUsage.INDIRECT
+ );
+
+ const indexedIndirectBuffer = t.makeBufferWithContents(
+ new Uint32Array([3, 1, 0, 0, 0]),
+ GPUBufferUsage.INDIRECT
+ );
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPassEncoder = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ maxDrawCount,
+ });
+
+ const firstHalfEncoder = bundleFirstHalf
+ ? t.device.createRenderBundleEncoder({
+ colorFormats: [colorFormat],
+ })
+ : renderPassEncoder;
+
+ const secondHalfEncoder = bundleSecondHalf
+ ? t.device.createRenderBundleEncoder({
+ colorFormats: [colorFormat],
+ })
+ : renderPassEncoder;
+
+ firstHalfEncoder.setPipeline(pipeline);
+ firstHalfEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ secondHalfEncoder.setPipeline(pipeline);
+ secondHalfEncoder.setIndexBuffer(indexBuffer, 'uint16');
+
+ const halfDrawCount = Math.floor(drawCount / 2);
+ for (let i = 0; i < drawCount; i++) {
+ const encoder = i < halfDrawCount ? firstHalfEncoder : secondHalfEncoder;
+ if (i % 4 === 0) {
+ encoder.draw(3);
+ }
+ if (i % 4 === 1) {
+ encoder.drawIndexed(3);
+ }
+ if (i % 4 === 2) {
+ encoder.drawIndirect(indirectBuffer, 0);
+ }
+ if (i % 4 === 3) {
+ encoder.drawIndexedIndirect(indexedIndirectBuffer, 0);
+ }
+ }
+
+ const bundles = [];
+ if (bundleFirstHalf) {
+ bundles.push(firstHalfEncoder.finish());
+ }
+ if (bundleSecondHalf) {
+ bundles.push(secondHalfEncoder.finish());
+ }
+
+ if (bundles.length > 0) {
+ renderPassEncoder.executeBundles(bundles);
+ }
+
+ renderPassEncoder.end();
+
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ }, drawCount > maxDrawCount);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/dynamic_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/dynamic_state.spec.js
new file mode 100644
index 0000000000..690c3313a3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/dynamic_state.spec.js
@@ -0,0 +1,296 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API validation tests for dynamic state commands (setViewport/ScissorRect/BlendColor...).
+
+TODO: ensure existing tests cover these notes. Note many of these may be operation tests instead.
+> - setViewport
+> - {x, y} = {0, invalid values if any}
+> - {width, height, minDepth, maxDepth} = {
+> - least possible value that's valid
+> - greatest possible negative value that's invalid
+> - greatest possible positive value that's valid
+> - least possible positive value that's invalid if any
+> - }
+> - minDepth {<, =, >} maxDepth
+> - setScissorRect
+> - {width, height} = 0
+> - {x+width, y+height} = attachment size + 1
+> - setBlendConstant
+> - color {slightly, very} out of range
+> - used with a simple pipeline that {does, doesn't} use it
+> - setStencilReference
+> - {0, max}
+> - used with a simple pipeline that {does, doesn't} use it
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+class F extends ValidationTest {
+ testViewportCall(success, v, attachmentSize = { width: 1, height: 1, depthOrArrayLayers: 1 }) {
+ const attachment = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: attachmentSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachment.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setViewport(v.x, v.y, v.w, v.h, v.minDepth, v.maxDepth);
+ pass.end();
+
+ this.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ }
+
+ testScissorCall(success, s, attachmentSize = { width: 1, height: 1, depthOrArrayLayers: 1 }) {
+ const attachment = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: attachmentSize,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachment.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ if (success === 'type-error') {
+ this.shouldThrow('TypeError', () => {
+ pass.setScissorRect(s.x, s.y, s.w, s.h);
+ });
+ } else {
+ pass.setScissorRect(s.x, s.y, s.w, s.h);
+ pass.end();
+
+ this.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ }
+ }
+
+ createDummyRenderPassEncoder() {
+ const attachment = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachment.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ return { encoder, pass };
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('setViewport,x_y_width_height_nonnegative')
+ .desc(
+ `Test that the parameters of setViewport to define the box must be non-negative.
+
+TODO Test -0 (it should be valid) but can't be tested because the harness complains about duplicate parameters.
+TODO Test the first value smaller than -0`
+ )
+ .paramsSubcasesOnly([
+ // Control case: everything to 0 is ok, covers the empty viewport case.
+ { x: 0, y: 0, w: 0, h: 0 },
+
+ // Test -1
+ { x: -1, y: 0, w: 0, h: 0 },
+ { x: 0, y: -1, w: 0, h: 0 },
+ { x: 0, y: 0, w: -1, h: 0 },
+ { x: 0, y: 0, w: 0, h: -1 },
+ ])
+ .fn(t => {
+ const { x, y, w, h } = t.params;
+ const success = x >= 0 && y >= 0 && w >= 0 && h >= 0;
+ t.testViewportCall(success, { x, y, w, h, minDepth: 0, maxDepth: 1 });
+ });
+
+g.test('setViewport,xy_rect_contained_in_attachment')
+ .desc(
+ 'Test that the rectangle defined by x, y, width, height must be contained in the attachments'
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combineWithParams([
+ { attachmentWidth: 3, attachmentHeight: 5 },
+ { attachmentWidth: 5, attachmentHeight: 3 },
+ { attachmentWidth: 1024, attachmentHeight: 1 },
+ { attachmentWidth: 1, attachmentHeight: 1024 },
+ ])
+ .combineWithParams([
+ // Control case: a full viewport is valid.
+ { dx: 0, dy: 0, dw: 0, dh: 0 },
+
+ // Other valid cases with a partial viewport.
+ { dx: 1, dy: 0, dw: -1, dh: 0 },
+ { dx: 0, dy: 1, dw: 0, dh: -1 },
+ { dx: 0, dy: 0, dw: -1, dh: 0 },
+ { dx: 0, dy: 0, dw: 0, dh: -1 },
+
+ // Test with a small value that causes the viewport to go outside the attachment.
+ { dx: 1, dy: 0, dw: 0, dh: 0 },
+ { dx: 0, dy: 1, dw: 0, dh: 0 },
+ { dx: 0, dy: 0, dw: 1, dh: 0 },
+ { dx: 0, dy: 0, dw: 0, dh: 1 },
+ ])
+ )
+ .fn(t => {
+ const { attachmentWidth, attachmentHeight, dx, dy, dw, dh } = t.params;
+ const x = dx;
+ const y = dy;
+ const w = attachmentWidth + dw;
+ const h = attachmentWidth + dh;
+
+ const success = x + w <= attachmentWidth && y + h <= attachmentHeight;
+ t.testViewportCall(
+ success,
+ { x, y, w, h, minDepth: 0, maxDepth: 1 },
+ { width: attachmentWidth, height: attachmentHeight, depthOrArrayLayers: 1 }
+ );
+ });
+
+g.test('setViewport,depth_rangeAndOrder')
+ .desc('Test that 0 <= minDepth <= maxDepth <= 1')
+ .paramsSubcasesOnly([
+ // Success cases
+ { minDepth: 0, maxDepth: 1 },
+ { minDepth: -0, maxDepth: -0 },
+ { minDepth: 1, maxDepth: 1 },
+ { minDepth: 0.3, maxDepth: 0.7 },
+ { minDepth: 0.7, maxDepth: 0.7 },
+ { minDepth: 0.3, maxDepth: 0.3 },
+
+ // Invalid cases
+ { minDepth: -0.1, maxDepth: 1 },
+ { minDepth: 0, maxDepth: 1.1 },
+ { minDepth: 0.5, maxDepth: 0.49999 },
+ ])
+ .fn(t => {
+ const { minDepth, maxDepth } = t.params;
+ const success =
+ 0 <= minDepth && minDepth <= 1 && 0 <= maxDepth && maxDepth <= 1 && minDepth <= maxDepth;
+ t.testViewportCall(success, { x: 0, y: 0, w: 1, h: 1, minDepth, maxDepth });
+ });
+
+g.test('setScissorRect,x_y_width_height_nonnegative')
+ .desc(
+ `Test that the parameters of setScissorRect to define the box must be non-negative or a TypeError is thrown.
+
+TODO Test -0 (it should be valid) but can't be tested because the harness complains about duplicate parameters.
+TODO Test the first value smaller than -0`
+ )
+ .paramsSubcasesOnly([
+ // Control case: everything to 0 is ok, covers the empty scissor case.
+ { x: 0, y: 0, w: 0, h: 0 },
+
+ // Test -1
+ { x: -1, y: 0, w: 0, h: 0 },
+ { x: 0, y: -1, w: 0, h: 0 },
+ { x: 0, y: 0, w: -1, h: 0 },
+ { x: 0, y: 0, w: 0, h: -1 },
+ ])
+ .fn(t => {
+ const { x, y, w, h } = t.params;
+ const success = x >= 0 && y >= 0 && w >= 0 && h >= 0;
+ t.testScissorCall(success ? true : 'type-error', { x, y, w, h });
+ });
+
+g.test('setScissorRect,xy_rect_contained_in_attachment')
+ .desc(
+ 'Test that the rectangle defined by x, y, width, height must be contained in the attachments'
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combineWithParams([
+ { attachmentWidth: 3, attachmentHeight: 5 },
+ { attachmentWidth: 5, attachmentHeight: 3 },
+ { attachmentWidth: 1024, attachmentHeight: 1 },
+ { attachmentWidth: 1, attachmentHeight: 1024 },
+ ])
+ .combineWithParams([
+ // Control case: a full scissor is valid.
+ { dx: 0, dy: 0, dw: 0, dh: 0 },
+
+ // Other valid cases with a partial scissor.
+ { dx: 1, dy: 0, dw: -1, dh: 0 },
+ { dx: 0, dy: 1, dw: 0, dh: -1 },
+ { dx: 0, dy: 0, dw: -1, dh: 0 },
+ { dx: 0, dy: 0, dw: 0, dh: -1 },
+
+ // Test with a small value that causes the scissor to go outside the attachment.
+ { dx: 1, dy: 0, dw: 0, dh: 0 },
+ { dx: 0, dy: 1, dw: 0, dh: 0 },
+ { dx: 0, dy: 0, dw: 1, dh: 0 },
+ { dx: 0, dy: 0, dw: 0, dh: 1 },
+ ])
+ )
+ .fn(t => {
+ const { attachmentWidth, attachmentHeight, dx, dy, dw, dh } = t.params;
+ const x = dx;
+ const y = dy;
+ const w = attachmentWidth + dw;
+ const h = attachmentWidth + dh;
+
+ const success = x + w <= attachmentWidth && y + h <= attachmentHeight;
+ t.testScissorCall(
+ success,
+ { x, y, w, h },
+ { width: attachmentWidth, height: attachmentHeight, depthOrArrayLayers: 1 }
+ );
+ });
+
+g.test('setBlendConstant')
+ .desc('Test that almost any color value is valid for setBlendConstant')
+ .paramsSubcasesOnly([
+ { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
+ { r: -1.0, g: -1.0, b: -1.0, a: -1.0 },
+ { r: Number.MAX_SAFE_INTEGER, g: Number.MIN_SAFE_INTEGER, b: -0, a: 100000 },
+ ])
+ .fn(t => {
+ const { r, g, b, a } = t.params;
+ const encoders = t.createDummyRenderPassEncoder();
+ encoders.pass.setBlendConstant({ r, g, b, a });
+ encoders.pass.end();
+ encoders.encoder.finish();
+ });
+
+g.test('setStencilReference')
+ .desc('Test that almost any stencil reference value is valid for setStencilReference')
+ .paramsSubcasesOnly([
+ { value: 1 }, //
+ { value: 0 },
+ { value: 1000 },
+ { value: 0xffffffff },
+ ])
+ .fn(t => {
+ const { value } = t.params;
+ const encoders = t.createDummyRenderPassEncoder();
+ encoders.pass.setStencilReference(value);
+ encoders.pass.end();
+ encoders.encoder.finish();
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.js
new file mode 100644
index 0000000000..2b968cc72d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.js
@@ -0,0 +1,203 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for drawIndirect/drawIndexedIndirect on render pass and render bundle.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../../../constants.js';
+import { kResourceStates } from '../../../../../gpu_test.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+import { kRenderEncodeTypeParams } from './render.js';
+
+const kIndirectDrawTestParams = kRenderEncodeTypeParams.combine('indexed', [true, false]);
+
+class F extends ValidationTest {
+ makeIndexBuffer() {
+ return this.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.INDEX,
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('indirect_buffer_state')
+ .desc(
+ `
+Tests indirect buffer must be valid.
+ `
+ )
+ .paramsSubcasesOnly(kIndirectDrawTestParams.combine('state', kResourceStates))
+ .fn(t => {
+ const { encoderType, indexed, state } = t.params;
+ const pipeline = t.createNoOpRenderPipeline();
+ const indirectBuffer = t.createBufferWithState(state, {
+ size: 256,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+
+ const { encoder, validateFinishAndSubmitGivenState } = t.createEncoder(encoderType);
+ encoder.setPipeline(pipeline);
+ if (indexed) {
+ const indexBuffer = t.makeIndexBuffer();
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ encoder.drawIndexedIndirect(indirectBuffer, 0);
+ } else {
+ encoder.drawIndirect(indirectBuffer, 0);
+ }
+
+ validateFinishAndSubmitGivenState(state);
+ });
+
+g.test('indirect_buffer,device_mismatch')
+ .desc(
+ 'Tests draw(Indexed)Indirect cannot be called with an indirect buffer created from another device'
+ )
+ .paramsSubcasesOnly(kIndirectDrawTestParams.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { encoderType, indexed, mismatched } = t.params;
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const indirectBuffer = sourceDevice.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+ t.trackForCleanup(indirectBuffer);
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(t.createNoOpRenderPipeline());
+
+ if (indexed) {
+ encoder.setIndexBuffer(t.makeIndexBuffer(), 'uint32');
+ encoder.drawIndexedIndirect(indirectBuffer, 0);
+ } else {
+ encoder.drawIndirect(indirectBuffer, 0);
+ }
+ validateFinish(!mismatched);
+ });
+
+g.test('indirect_buffer_usage')
+ .desc(
+ `
+Tests indirect buffer must have 'Indirect' usage.
+ `
+ )
+ .paramsSubcasesOnly(
+ kIndirectDrawTestParams.combine('usage', [
+ GPUConst.BufferUsage.INDIRECT, // control case
+ GPUConst.BufferUsage.COPY_DST,
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.INDIRECT,
+ ])
+ )
+ .fn(t => {
+ const { encoderType, indexed, usage } = t.params;
+ const indirectBuffer = t.device.createBuffer({
+ size: 256,
+ usage,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(t.createNoOpRenderPipeline());
+ if (indexed) {
+ const indexBuffer = t.makeIndexBuffer();
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ encoder.drawIndexedIndirect(indirectBuffer, 0);
+ } else {
+ encoder.drawIndirect(indirectBuffer, 0);
+ }
+ validateFinish((usage & GPUBufferUsage.INDIRECT) !== 0);
+ });
+
+g.test('indirect_offset_alignment')
+ .desc(
+ `
+Tests indirect offset must be a multiple of 4.
+ `
+ )
+ .paramsSubcasesOnly(kIndirectDrawTestParams.combine('indirectOffset', [0, 2, 4]))
+ .fn(t => {
+ const { encoderType, indexed, indirectOffset } = t.params;
+ const pipeline = t.createNoOpRenderPipeline();
+ const indirectBuffer = t.device.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(pipeline);
+ if (indexed) {
+ const indexBuffer = t.makeIndexBuffer();
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ encoder.drawIndexedIndirect(indirectBuffer, indirectOffset);
+ } else {
+ encoder.drawIndirect(indirectBuffer, indirectOffset);
+ }
+
+ validateFinish(indirectOffset % 4 === 0);
+ });
+
+g.test('indirect_offset_oob')
+ .desc(
+ `
+Tests indirect draw calls with various indirect offsets and buffer sizes.
+- (offset, b.size) is
+ - (0, 0)
+ - (0, min size) (control case)
+ - (0, min size + 1) (control case)
+ - (0, min size - 1)
+ - (0, min size - min alignment)
+ - (min alignment, min size + min alignment)
+ - (min alignment, min size + min alignment - 1)
+ - (min alignment / 2, min size + min alignment)
+ - (min alignment +/- 1, min size + min alignment)
+ - (min size, min size)
+ - (min size + min alignment, min size)
+ - min size = indirect draw parameters size
+ - x =(drawIndirect, drawIndexedIndirect)
+ `
+ )
+ .paramsSubcasesOnly(
+ kIndirectDrawTestParams.expandWithParams(p => {
+ const indirectParamsSize = p.indexed ? 20 : 16;
+ return [
+ { indirectOffset: 0, bufferSize: 0, _valid: false },
+ { indirectOffset: 0, bufferSize: indirectParamsSize, _valid: true },
+ { indirectOffset: 0, bufferSize: indirectParamsSize + 1, _valid: true },
+ { indirectOffset: 0, bufferSize: indirectParamsSize - 1, _valid: false },
+ { indirectOffset: 0, bufferSize: indirectParamsSize - 4, _valid: false },
+ { indirectOffset: 4, bufferSize: indirectParamsSize + 4, _valid: true },
+ { indirectOffset: 4, bufferSize: indirectParamsSize + 3, _valid: false },
+ { indirectOffset: 2, bufferSize: indirectParamsSize + 4, _valid: false },
+ { indirectOffset: 3, bufferSize: indirectParamsSize + 4, _valid: false },
+ { indirectOffset: 5, bufferSize: indirectParamsSize + 4, _valid: false },
+ { indirectOffset: indirectParamsSize, bufferSize: indirectParamsSize, _valid: false },
+ { indirectOffset: indirectParamsSize + 4, bufferSize: indirectParamsSize, _valid: false },
+ ];
+ })
+ )
+ .fn(t => {
+ const { encoderType, indexed, indirectOffset, bufferSize, _valid } = t.params;
+ const pipeline = t.createNoOpRenderPipeline();
+ const indirectBuffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(pipeline);
+ if (indexed) {
+ const indexBuffer = t.makeIndexBuffer();
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ encoder.drawIndexedIndirect(indirectBuffer, indirectOffset);
+ } else {
+ encoder.drawIndirect(indirectBuffer, indirectOffset);
+ }
+
+ validateFinish(_valid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/render.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/render.js
new file mode 100644
index 0000000000..ce8cae256e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/render.js
@@ -0,0 +1,30 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { kUnitCaseParamsBuilder } from '../../../../../../common/framework/params_builder.js';
+import { kRenderEncodeTypes } from '../../../../../util/command_buffer_maker.js';
+export const kRenderEncodeTypeParams = kUnitCaseParamsBuilder.combine(
+ 'encoderType',
+ kRenderEncodeTypes
+);
+
+export function buildBufferOffsetAndSizeOOBTestParams(minAlignment, bufferSize) {
+ return kRenderEncodeTypeParams.combineWithParams([
+ // Explicit size
+ { offset: 0, size: 0, _valid: true },
+ { offset: 0, size: 1, _valid: true },
+ { offset: 0, size: 4, _valid: true },
+ { offset: 0, size: 5, _valid: true },
+ { offset: 0, size: bufferSize, _valid: true },
+ { offset: 0, size: bufferSize + 4, _valid: false },
+ { offset: minAlignment, size: bufferSize, _valid: false },
+ { offset: minAlignment, size: bufferSize - minAlignment, _valid: true },
+ { offset: bufferSize - minAlignment, size: minAlignment, _valid: true },
+ { offset: bufferSize, size: 1, _valid: false },
+ // Implicit size: buffer.size - offset
+ { offset: 0, size: undefined, _valid: true },
+ { offset: minAlignment, size: undefined, _valid: true },
+ { offset: bufferSize - minAlignment, size: undefined, _valid: true },
+ { offset: bufferSize, size: undefined, _valid: true },
+ { offset: bufferSize + minAlignment, size: undefined, _valid: false },
+ ]);
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.js
new file mode 100644
index 0000000000..3d64af66df
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.js
@@ -0,0 +1,123 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for setIndexBuffer on render pass and render bundle.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../../../constants.js';
+import { kResourceStates } from '../../../../../gpu_test.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+import { kRenderEncodeTypeParams, buildBufferOffsetAndSizeOOBTestParams } from './render.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('index_buffer_state')
+ .desc(
+ `
+Tests index buffer must be valid.
+ `
+ )
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('state', kResourceStates))
+ .fn(t => {
+ const { encoderType, state } = t.params;
+ const indexBuffer = t.createBufferWithState(state, {
+ size: 16,
+ usage: GPUBufferUsage.INDEX,
+ });
+
+ const { encoder, validateFinishAndSubmitGivenState } = t.createEncoder(encoderType);
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ validateFinishAndSubmitGivenState(state);
+ });
+
+g.test('index_buffer,device_mismatch')
+ .desc('Tests setIndexBuffer cannot be called with an index buffer created from another device')
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { encoderType, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const indexBuffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.INDEX,
+ });
+ t.trackForCleanup(indexBuffer);
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ validateFinish(!mismatched);
+ });
+
+g.test('index_buffer_usage')
+ .desc(
+ `
+Tests index buffer must have 'Index' usage.
+ `
+ )
+ .paramsSubcasesOnly(
+ kRenderEncodeTypeParams.combine('usage', [
+ GPUConst.BufferUsage.INDEX, // control case
+ GPUConst.BufferUsage.COPY_DST,
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.INDEX,
+ ])
+ )
+ .fn(t => {
+ const { encoderType, usage } = t.params;
+ const indexBuffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setIndexBuffer(indexBuffer, 'uint32');
+ validateFinish((usage & GPUBufferUsage.INDEX) !== 0);
+ });
+
+g.test('offset_alignment')
+ .desc(
+ `
+Tests offset must be a multiple of index format’s byte size.
+ `
+ )
+ .paramsSubcasesOnly(
+ kRenderEncodeTypeParams.combine('indexFormat', ['uint16', 'uint32']).expand('offset', p => {
+ return p.indexFormat === 'uint16' ? [0, 1, 2] : [0, 2, 4];
+ })
+ )
+ .fn(t => {
+ const { encoderType, indexFormat, offset } = t.params;
+ const indexBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.INDEX,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setIndexBuffer(indexBuffer, indexFormat, offset);
+
+ const alignment =
+ indexFormat === 'uint16' ? Uint16Array.BYTES_PER_ELEMENT : Uint32Array.BYTES_PER_ELEMENT;
+ validateFinish(offset % alignment === 0);
+ });
+
+g.test('offset_and_size_oob')
+ .desc(
+ `
+Tests offset and size cannot be larger than index buffer size.
+ `
+ )
+ .paramsSubcasesOnly(buildBufferOffsetAndSizeOOBTestParams(4, 256))
+ .fn(t => {
+ const { encoderType, offset, size, _valid } = t.params;
+ const indexBuffer = t.device.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.INDEX,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setIndexBuffer(indexBuffer, 'uint32', offset, size);
+ validateFinish(_valid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.js
new file mode 100644
index 0000000000..67f7246e0f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for setPipeline on render pass and render bundle.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { kRenderEncodeTypes } from '../../../../../util/command_buffer_maker.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+import { kRenderEncodeTypeParams } from './render.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('invalid_pipeline')
+ .desc(
+ `
+Tests setPipeline should generate an error iff using an 'invalid' pipeline.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('encoderType', kRenderEncodeTypes).combine('state', ['valid', 'invalid'])
+ )
+ .fn(t => {
+ const { encoderType, state } = t.params;
+ const pipeline = t.createRenderPipelineWithState(state);
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(pipeline);
+ validateFinish(state !== 'invalid');
+ });
+
+g.test('pipeline,device_mismatch')
+ .desc('Tests setPipeline cannot be called with a render pipeline created from another device')
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { encoderType, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const pipeline = sourceDevice.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: sourceDevice.createShaderModule({
+ code: `@vertex fn main() -> @builtin(position) vec4<f32> { return vec4<f32>(); }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: sourceDevice.createShaderModule({
+ code: '@fragment fn main() {}',
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setPipeline(pipeline);
+ validateFinish(!mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.js
new file mode 100644
index 0000000000..28bfff2264
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.js
@@ -0,0 +1,142 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for setVertexBuffer on render pass and render bundle.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { kLimitInfo } from '../../../../../capability_info.js';
+import { GPUConst } from '../../../../../constants.js';
+import { kResourceStates } from '../../../../../gpu_test.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+import { kRenderEncodeTypeParams, buildBufferOffsetAndSizeOOBTestParams } from './render.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('slot')
+ .desc(
+ `
+Tests slot must be less than the maxVertexBuffers in device limits.
+ `
+ )
+ .paramsSubcasesOnly(
+ kRenderEncodeTypeParams.combine('slot', [
+ 0,
+ kLimitInfo.maxVertexBuffers.default - 1,
+ kLimitInfo.maxVertexBuffers.default,
+ ])
+ )
+ .fn(t => {
+ const { encoderType, slot } = t.params;
+ const vertexBuffer = t.createBufferWithState('valid', {
+ size: 16,
+ usage: GPUBufferUsage.VERTEX,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(slot, vertexBuffer);
+ validateFinish(slot < kLimitInfo.maxVertexBuffers.default);
+ });
+
+g.test('vertex_buffer_state')
+ .desc(
+ `
+Tests vertex buffer must be valid.
+ `
+ )
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('state', kResourceStates))
+ .fn(t => {
+ const { encoderType, state } = t.params;
+ const vertexBuffer = t.createBufferWithState(state, {
+ size: 16,
+ usage: GPUBufferUsage.VERTEX,
+ });
+
+ const { encoder, validateFinishAndSubmitGivenState } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(0, vertexBuffer);
+ validateFinishAndSubmitGivenState(state);
+ });
+
+g.test('vertex_buffer,device_mismatch')
+ .desc('Tests setVertexBuffer cannot be called with a vertex buffer created from another device')
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { encoderType, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const vertexBuffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.VERTEX,
+ });
+ t.trackForCleanup(vertexBuffer);
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(0, vertexBuffer);
+ validateFinish(!mismatched);
+ });
+
+g.test('vertex_buffer_usage')
+ .desc(
+ `
+Tests vertex buffer must have 'Vertex' usage.
+ `
+ )
+ .paramsSubcasesOnly(
+ kRenderEncodeTypeParams.combine('usage', [
+ GPUConst.BufferUsage.VERTEX, // control case
+ GPUConst.BufferUsage.COPY_DST,
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.VERTEX,
+ ])
+ )
+ .fn(t => {
+ const { encoderType, usage } = t.params;
+ const vertexBuffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(0, vertexBuffer);
+ validateFinish((usage & GPUBufferUsage.VERTEX) !== 0);
+ });
+
+g.test('offset_alignment')
+ .desc(
+ `
+Tests offset must be a multiple of 4.
+ `
+ )
+ .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('offset', [0, 2, 4]))
+ .fn(t => {
+ const { encoderType, offset } = t.params;
+ const vertexBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.VERTEX,
+ });
+
+ const { encoder, validateFinish: finish } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(0, vertexBuffer, offset);
+ finish(offset % 4 === 0);
+ });
+
+g.test('offset_and_size_oob')
+ .desc(
+ `
+Tests offset and size cannot be larger than vertex buffer size.
+ `
+ )
+ .paramsSubcasesOnly(buildBufferOffsetAndSizeOOBTestParams(4, 256))
+ .fn(t => {
+ const { encoderType, offset, size, _valid } = t.params;
+ const vertexBuffer = t.device.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.VERTEX,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setVertexBuffer(0, vertexBuffer, offset, size);
+ validateFinish(_valid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.js
new file mode 100644
index 0000000000..d403697298
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.js
@@ -0,0 +1,185 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for setVertexBuffer/setIndexBuffer state (not validation). See also operation tests.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { range } from '../../../../../../common/util/util.js';
+import { ValidationTest } from '../../../validation_test.js';
+
+class F extends ValidationTest {
+ getVertexBuffer() {
+ return this.device.createBuffer({
+ size: 256,
+ usage: GPUBufferUsage.VERTEX,
+ });
+ }
+
+ createRenderPipeline(bufferCount) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ struct Inputs {
+ ${range(bufferCount, i => `\n@location(${i}) a_position${i} : vec3<f32>,`).join('')}
+ };
+ @vertex fn main(input : Inputs
+ ) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ buffers: [
+ {
+ arrayStride: 3 * 4,
+ attributes: range(bufferCount, i => ({
+ format: 'float32x3',
+ offset: 0,
+ shaderLocation: i,
+ })),
+ },
+ ],
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ }
+
+ beginRenderPass(commandEncoder) {
+ const attachmentTexture = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ return commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachmentTexture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test(`all_needed_vertex_buffer_should_be_bound`)
+ .desc(
+ `
+In this test we test that any missing vertex buffer for a used slot will cause validation errors when drawing.
+- All (non/indexed, in/direct) draw commands
+ - A needed vertex buffer is not bound
+ - Was bound in another render pass but not the current one
+`
+ )
+ .unimplemented();
+
+g.test(`all_needed_index_buffer_should_be_bound`)
+ .desc(
+ `
+In this test we test that missing index buffer for a used slot will cause validation errors when drawing.
+- All indexed in/direct draw commands
+ - No index buffer is bound
+`
+ )
+ .unimplemented();
+
+g.test('vertex_buffers_inherit_from_previous_pipeline').fn(async t => {
+ const pipeline1 = t.createRenderPipeline(1);
+ const pipeline2 = t.createRenderPipeline(2);
+
+ const vertexBuffer1 = t.getVertexBuffer();
+ const vertexBuffer2 = t.getVertexBuffer();
+
+ {
+ // Check failure when vertex buffer is not set
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline1);
+ renderPass.draw(3);
+ renderPass.end();
+
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ });
+ }
+ {
+ // Check success when vertex buffer is inherited from previous pipeline
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline2);
+ renderPass.setVertexBuffer(0, vertexBuffer1);
+ renderPass.setVertexBuffer(1, vertexBuffer2);
+ renderPass.draw(3);
+ renderPass.setPipeline(pipeline1);
+ renderPass.draw(3);
+ renderPass.end();
+
+ commandEncoder.finish();
+ }
+});
+
+g.test('vertex_buffers_do_not_inherit_between_render_passes').fn(async t => {
+ const pipeline1 = t.createRenderPipeline(1);
+ const pipeline2 = t.createRenderPipeline(2);
+
+ const vertexBuffer1 = t.getVertexBuffer();
+ const vertexBuffer2 = t.getVertexBuffer();
+
+ {
+ // Check success when vertex buffer is set for each render pass
+ const commandEncoder = t.device.createCommandEncoder();
+ {
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline2);
+ renderPass.setVertexBuffer(0, vertexBuffer1);
+ renderPass.setVertexBuffer(1, vertexBuffer2);
+ renderPass.draw(3);
+ renderPass.end();
+ }
+ {
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline1);
+ renderPass.setVertexBuffer(0, vertexBuffer1);
+ renderPass.draw(3);
+ renderPass.end();
+ }
+ commandEncoder.finish();
+ }
+ {
+ // Check failure because vertex buffer is not inherited in second subpass
+ const commandEncoder = t.device.createCommandEncoder();
+ {
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline2);
+ renderPass.setVertexBuffer(0, vertexBuffer1);
+ renderPass.setVertexBuffer(1, vertexBuffer2);
+ renderPass.draw(3);
+ renderPass.end();
+ }
+ {
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline1);
+ renderPass.draw(3);
+ renderPass.end();
+ }
+
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ });
+ }
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render_pass.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render_pass.spec.js
new file mode 100644
index 0000000000..52e2a75514
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/render_pass.spec.js
@@ -0,0 +1,15 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for render pass encoding.
+Does **not** test usage scopes (resource_usages/), GPUProgrammablePassEncoder (programmable_pass),
+dynamic state (dynamic_render_state.spec.ts), or GPURenderEncoderBase (render.spec.ts).
+
+TODO:
+- executeBundles:
+ - with {zero, one, multiple} bundles where {zero, one} of them are invalid objects
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/setBindGroup.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/setBindGroup.spec.js
new file mode 100644
index 0000000000..4054097165
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/cmds/setBindGroup.spec.js
@@ -0,0 +1,436 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+setBindGroup validation tests.
+
+TODO: merge these notes and implement.
+> (Note: If there are errors with using certain binding types in certain passes, test those in the file for that pass type, not here.)
+>
+> - state tracking (probably separate file)
+> - x= {compute pass, render pass}
+> - {null, compatible, incompatible} current pipeline (should have no effect without draw/dispatch)
+> - setBindGroup in different orders (e.g. 0,1,2 vs 2,0,1)
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { range, unreachable } from '../../../../../common/util/util.js';
+import {
+ kBufferBindingTypes,
+ kMinDynamicBufferOffsetAlignment,
+ kLimitInfo,
+} from '../../../../capability_info.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { kProgrammableEncoderTypes } from '../../../../util/command_buffer_maker.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ encoderTypeToStageFlag(encoderType) {
+ switch (encoderType) {
+ case 'compute pass':
+ return GPUShaderStage.COMPUTE;
+ case 'render pass':
+ case 'render bundle':
+ return GPUShaderStage.FRAGMENT;
+ default:
+ unreachable('Unknown encoder type');
+ }
+ }
+
+ createBindingResourceWithState(resourceType, state) {
+ switch (resourceType) {
+ case 'texture': {
+ const texture = this.createTextureWithState('valid');
+ const view = texture.createView();
+ if (state === 'destroyed') {
+ texture.destroy();
+ }
+ return view;
+ }
+ case 'buffer':
+ return {
+ buffer: this.createBufferWithState(state, {
+ size: 4,
+ usage: GPUBufferUsage.STORAGE,
+ }),
+ };
+ default:
+ unreachable('unknown resource type');
+ }
+ }
+
+ /**
+ * If state is 'invalid', creates an invalid bind group with valid resources.
+ * If state is 'destroyed', creates a valid bind group with destroyed resources.
+ */
+ createBindGroup(state, resourceType, encoderType, indices) {
+ if (state === 'invalid') {
+ this.device.pushErrorScope('validation');
+ indices = new Array(indices.length + 1).fill(0);
+ }
+
+ const layout = this.device.createBindGroupLayout({
+ entries: indices.map(binding => ({
+ binding,
+ visibility: this.encoderTypeToStageFlag(encoderType),
+ ...(resourceType === 'buffer' ? { buffer: { type: 'storage' } } : { texture: {} }),
+ })),
+ });
+ const bindGroup = this.device.createBindGroup({
+ layout,
+ entries: indices.map(binding => ({
+ binding,
+ resource: this.createBindingResourceWithState(
+ resourceType,
+ state === 'destroyed' ? state : 'valid'
+ ),
+ })),
+ });
+
+ if (state === 'invalid') {
+ void this.device.popErrorScope();
+ }
+ return bindGroup;
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('state_and_binding_index')
+ .desc('Tests that setBindGroup correctly handles {valid, invalid, destroyed} bindGroups.')
+ .params(u =>
+ u
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .combine('state', kResourceStates)
+ .combine('resourceType', ['buffer', 'texture'])
+ )
+ .fn(async t => {
+ const { encoderType, state, resourceType } = t.params;
+ const maxBindGroups = t.device.limits.maxBindGroups;
+
+ async function runTest(index) {
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType);
+ encoder.setBindGroup(index, t.createBindGroup(state, resourceType, encoderType, [index]));
+
+ validateFinishAndSubmit(state !== 'invalid' && index < maxBindGroups, state !== 'destroyed');
+ }
+
+ // MAINTENANCE_TODO: move to subcases() once we can query the device limits
+ for (const index of [1, maxBindGroups - 1, maxBindGroups]) {
+ t.debug(`test bind group index ${index}`);
+ await runTest(index);
+ }
+ });
+
+g.test('bind_group,device_mismatch')
+ .desc(
+ `
+ Tests setBindGroup cannot be called with a bind group created from another device
+ - x= setBindGroup {sequence overload, Uint32Array overload}
+ `
+ )
+ .params(u =>
+ u
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .beginSubcases()
+ .combine('useU32Array', [true, false])
+ .combine('mismatched', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { encoderType, useU32Array, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const buffer = sourceDevice.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.STORAGE,
+ });
+
+ const layout = sourceDevice.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: t.encoderTypeToStageFlag(encoderType),
+ buffer: { type: 'storage', hasDynamicOffset: useU32Array },
+ },
+ ],
+ });
+
+ const bindGroup = sourceDevice.createBindGroup({
+ layout,
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer },
+ },
+ ],
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ if (useU32Array) {
+ encoder.setBindGroup(0, bindGroup, new Uint32Array([0]), 0, 1);
+ } else {
+ encoder.setBindGroup(0, bindGroup);
+ }
+ validateFinish(!mismatched);
+ });
+
+g.test('dynamic_offsets_passed_but_not_expected')
+ .desc('Tests that setBindGroup correctly errors on unexpected dynamicOffsets.')
+ .params(u => u.combine('encoderType', kProgrammableEncoderTypes))
+ .fn(async t => {
+ const { encoderType } = t.params;
+ const bindGroup = t.createBindGroup('valid', 'buffer', encoderType, []);
+ const dynamicOffsets = [0];
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setBindGroup(0, bindGroup, dynamicOffsets);
+ validateFinish(false);
+ });
+
+g.test('dynamic_offsets_match_expectations_in_pass_encoder')
+ .desc('Tests that given dynamicOffsets match the specified bindGroup.')
+ .params(u =>
+ u
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .combineWithParams([
+ { dynamicOffsets: [256, 0], _success: true }, // Dynamic offsets aligned
+ { dynamicOffsets: [1, 2], _success: false }, // Dynamic offsets not aligned
+
+ // Wrong number of dynamic offsets
+ { dynamicOffsets: [256, 0, 0], _success: false },
+ { dynamicOffsets: [256], _success: false },
+ { dynamicOffsets: [], _success: false },
+
+ // Dynamic uniform buffer out of bounds because of binding size
+ { dynamicOffsets: [512, 0], _success: false },
+ { dynamicOffsets: [1024, 0], _success: false },
+ { dynamicOffsets: [0xffffffff, 0], _success: false },
+
+ // Dynamic storage buffer out of bounds because of binding size
+ { dynamicOffsets: [0, 512], _success: false },
+ { dynamicOffsets: [0, 1024], _success: false },
+ { dynamicOffsets: [0, 0xffffffff], _success: false },
+ ])
+ .combine('useU32array', [false, true])
+ )
+ .fn(async t => {
+ const kBindingSize = 12;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
+ buffer: {
+ type: 'uniform',
+ hasDynamicOffset: true,
+ },
+ },
+ {
+ binding: 1,
+ visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
+ buffer: {
+ type: 'storage',
+ hasDynamicOffset: true,
+ },
+ },
+ ],
+ });
+
+ const uniformBuffer = t.device.createBuffer({
+ size: 2 * kMinDynamicBufferOffsetAlignment + 8,
+ usage: GPUBufferUsage.UNIFORM,
+ });
+
+ const storageBuffer = t.device.createBuffer({
+ size: 2 * kMinDynamicBufferOffsetAlignment + 8,
+ usage: GPUBufferUsage.STORAGE,
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ size: kBindingSize,
+ },
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: storageBuffer,
+ size: kBindingSize,
+ },
+ },
+ ],
+ });
+
+ const { encoderType, dynamicOffsets, useU32array, _success } = t.params;
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ if (useU32array) {
+ encoder.setBindGroup(0, bindGroup, new Uint32Array(dynamicOffsets), 0, dynamicOffsets.length);
+ } else {
+ encoder.setBindGroup(0, bindGroup, dynamicOffsets);
+ }
+ validateFinish(_success);
+ });
+
+g.test('u32array_start_and_length')
+ .desc('Tests that dynamicOffsetsData(Start|Length) apply to the given Uint32Array.')
+ .paramsSubcasesOnly([
+ // dynamicOffsetsDataLength > offsets.length
+ {
+ offsets: [0],
+ dynamicOffsetsDataStart: 0,
+ dynamicOffsetsDataLength: 2,
+ _success: false,
+ },
+ // dynamicOffsetsDataStart + dynamicOffsetsDataLength > offsets.length
+ {
+ offsets: [0],
+ dynamicOffsetsDataStart: 1,
+ dynamicOffsetsDataLength: 1,
+ _success: false,
+ },
+ {
+ offsets: [0, 0],
+ dynamicOffsetsDataStart: 1,
+ dynamicOffsetsDataLength: 1,
+ _success: true,
+ },
+ {
+ offsets: [0, 0, 0],
+ dynamicOffsetsDataStart: 1,
+ dynamicOffsetsDataLength: 1,
+ _success: true,
+ },
+ {
+ offsets: [0, 0],
+ dynamicOffsetsDataStart: 0,
+ dynamicOffsetsDataLength: 2,
+ _success: true,
+ },
+ ])
+ .fn(t => {
+ const { offsets, dynamicOffsetsDataStart, dynamicOffsetsDataLength, _success } = t.params;
+ const kBindingSize = 8;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: range(dynamicOffsetsDataLength, i => ({
+ binding: i,
+ visibility: GPUShaderStage.FRAGMENT,
+ buffer: {
+ type: 'storage',
+ hasDynamicOffset: true,
+ },
+ })),
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: range(dynamicOffsetsDataLength, i => ({
+ binding: i,
+ resource: {
+ buffer: t.createBufferWithState('valid', {
+ size: kBindingSize,
+ usage: GPUBufferUsage.STORAGE,
+ }),
+ size: kBindingSize,
+ },
+ })),
+ });
+
+ const { encoder, validateFinish } = t.createEncoder('render pass');
+
+ const doSetBindGroup = () => {
+ encoder.setBindGroup(
+ 0,
+ bindGroup,
+ new Uint32Array(offsets),
+ dynamicOffsetsDataStart,
+ dynamicOffsetsDataLength
+ );
+ };
+
+ if (_success) {
+ doSetBindGroup();
+ } else {
+ t.shouldThrow('RangeError', doSetBindGroup);
+ }
+
+ // RangeError in setBindGroup does not cause the encoder to become invalid.
+ validateFinish(true);
+ });
+
+g.test('buffer_dynamic_offsets')
+ .desc(
+ `
+ Test that the dynamic offsets of the BufferLayout is a multiple of
+ 'minUniformBufferOffsetAlignment|minStorageBufferOffsetAlignment' if the BindGroup entry defines
+ buffer and the buffer type is 'uniform|storage|read-only-storage'.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('type', kBufferBindingTypes)
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .beginSubcases()
+ .expand('dynamicOffset', ({ type }) =>
+ type === 'uniform'
+ ? [
+ kLimitInfo.minUniformBufferOffsetAlignment.default,
+ kLimitInfo.minUniformBufferOffsetAlignment.default * 0.5,
+ kLimitInfo.minUniformBufferOffsetAlignment.default * 1.5,
+ kLimitInfo.minUniformBufferOffsetAlignment.default * 2,
+ kLimitInfo.minUniformBufferOffsetAlignment.default + 2,
+ ]
+ : [
+ kLimitInfo.minStorageBufferOffsetAlignment.default,
+ kLimitInfo.minStorageBufferOffsetAlignment.default * 0.5,
+ kLimitInfo.minStorageBufferOffsetAlignment.default * 1.5,
+ kLimitInfo.minStorageBufferOffsetAlignment.default * 2,
+ kLimitInfo.minStorageBufferOffsetAlignment.default + 2,
+ ]
+ )
+ )
+ .fn(async t => {
+ const { type, dynamicOffset, encoderType } = t.params;
+ const kBindingSize = 12;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: { type, hasDynamicOffset: true },
+ },
+ ],
+ });
+
+ let usage, isValid;
+ if (type === 'uniform') {
+ usage = GPUBufferUsage.UNIFORM;
+ isValid = dynamicOffset % kLimitInfo.minUniformBufferOffsetAlignment.default === 0;
+ } else {
+ usage = GPUBufferUsage.STORAGE;
+ isValid = dynamicOffset % kLimitInfo.minStorageBufferOffsetAlignment.default === 0;
+ }
+
+ const buffer = t.device.createBuffer({
+ size: 3 * kMinDynamicBufferOffsetAlignment,
+ usage,
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ entries: [{ binding: 0, resource: { buffer, size: kBindingSize } }],
+ layout: bindGroupLayout,
+ });
+
+ const { encoder, validateFinish } = t.createEncoder(encoderType);
+ encoder.setBindGroup(0, bindGroup, [dynamicOffset]);
+ validateFinish(isValid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js
new file mode 100644
index 0000000000..61cb2ad9ba
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.js
@@ -0,0 +1,229 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+createRenderBundleEncoder validation tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import {
+ kAllTextureFormats,
+ kDepthStencilFormats,
+ kTextureFormatInfo,
+ kMaxColorAttachments,
+ kRenderableColorTextureFormats,
+} from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('attachment_state,limits,maxColorAttachments')
+ .desc(`Tests that attachment state must have <= device.limits.maxColorAttachments.`)
+ .params(u =>
+ u.beginSubcases().combine(
+ 'colorFormatCount',
+ range(kMaxColorAttachments + 1, i => i + 1) // 1-9
+ )
+ )
+ .fn(async t => {
+ const { colorFormatCount } = t.params;
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: Array(colorFormatCount).fill('r8unorm'),
+ });
+ }, colorFormatCount > t.device.limits.maxColorAttachments);
+ });
+
+g.test('attachment_state,limits,maxColorAttachmentBytesPerSample,aligned')
+ .desc(
+ `
+ Tests that the total color attachment bytes per sample <=
+ device.limits.maxColorAttachmentBytesPerSample when using the same format (aligned) for multiple
+ attachments.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine(
+ 'colorFormatCount',
+ range(kMaxColorAttachments, i => i + 1)
+ )
+ )
+ .fn(async t => {
+ const { format, colorFormatCount } = t.params;
+ const info = kTextureFormatInfo[format];
+ const shouldError =
+ info.renderTargetPixelByteCost === undefined ||
+ info.renderTargetPixelByteCost * colorFormatCount >
+ t.device.limits.maxColorAttachmentBytesPerSample;
+
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: Array(colorFormatCount).fill(format),
+ });
+ }, shouldError);
+ });
+
+g.test('attachment_state,limits,maxColorAttachmentBytesPerSample,unaligned')
+ .desc(
+ `
+ Tests that the total color attachment bytes per sample <=
+ device.limits.maxColorAttachmentBytesPerSample when using various sets of (potentially)
+ unaligned formats.
+ `
+ )
+ .params(u =>
+ u.combineWithParams([
+ // Alignment causes the first 1 byte R8Unorm to become 4 bytes. So even though
+ // 1+4+8+16+1 < 32, the 4 byte alignment requirement of R32Float makes the first R8Unorm
+ // become 4 and 4+4+8+16+1 > 32. Re-ordering this so the R8Unorm's are at the end, however
+ // is allowed: 4+8+16+1+1 < 32.
+ {
+ formats: ['r8unorm', 'r32float', 'rgba8unorm', 'rgba32float', 'r8unorm'],
+
+ _shouldError: false,
+ },
+ {
+ formats: ['r32float', 'rgba8unorm', 'rgba32float', 'r8unorm', 'r8unorm'],
+
+ _shouldError: true,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { formats, _shouldError } = t.params;
+
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: formats,
+ });
+ }, _shouldError);
+ });
+
+g.test('attachment_state,empty_color_formats')
+ .desc(`Tests that if no colorFormats are given, a depthStencilFormat must be specified.`)
+ .params(u => u.beginSubcases().combine('depthStencilFormat', [undefined, 'depth24plus-stencil8']))
+ .fn(async t => {
+ const { depthStencilFormat } = t.params;
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [],
+ depthStencilFormat,
+ });
+ }, depthStencilFormat === undefined);
+ });
+
+g.test('valid_texture_formats')
+ .desc(
+ `
+ Tests that createRenderBundleEncoder only accepts valid formats for its attachments.
+ - colorFormats
+ - depthStencilFormat
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kAllTextureFormats)
+ .beginSubcases()
+ .combine('attachment', ['color', 'depthStencil'])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const { format, attachment } = t.params;
+
+ const colorRenderable =
+ kTextureFormatInfo[format].renderable && kTextureFormatInfo[format].color;
+
+ const depthStencil = kTextureFormatInfo[format].depth || kTextureFormatInfo[format].stencil;
+
+ switch (attachment) {
+ case 'color': {
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [format],
+ });
+ }, !colorRenderable);
+
+ break;
+ }
+ case 'depthStencil': {
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [],
+ depthStencilFormat: format,
+ });
+ }, !depthStencil);
+
+ break;
+ }
+ }
+ });
+
+g.test('depth_stencil_readonly')
+ .desc(
+ `
+ Tests that createRenderBundleEncoder validation of depthReadOnly and stencilReadOnly
+ - With depth-only formats
+ - With stencil-only formats
+ - With depth-stencil-combined formats
+ `
+ )
+ .params(u =>
+ u //
+ .combine('depthStencilFormat', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('depthReadOnly', [false, true])
+ .combine('stencilReadOnly', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { depthStencilFormat } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(depthStencilFormat);
+ })
+ .fn(async t => {
+ const { depthStencilFormat, depthReadOnly, stencilReadOnly } = t.params;
+
+ let shouldError = false;
+ if (
+ kTextureFormatInfo[depthStencilFormat].depth &&
+ kTextureFormatInfo[depthStencilFormat].stencil &&
+ depthReadOnly !== stencilReadOnly
+ ) {
+ shouldError = true;
+ }
+
+ t.expectValidationError(() => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [],
+ depthStencilFormat,
+ depthReadOnly,
+ stencilReadOnly,
+ });
+ }, shouldError);
+ });
+
+g.test('depth_stencil_readonly_with_undefined_depth')
+ .desc(
+ `
+ Tests that createRenderBundleEncoder validation of depthReadOnly and stencilReadOnly is ignored
+ if there is no depthStencilFormat set.
+ `
+ )
+ .params(u =>
+ u //
+ .beginSubcases()
+ .combine('depthReadOnly', [false, true])
+ .combine('stencilReadOnly', [false, true])
+ )
+ .fn(async t => {
+ const { depthReadOnly, stencilReadOnly } = t.params;
+
+ t.device.createRenderBundleEncoder({
+ colorFormats: ['bgra8unorm'],
+ depthReadOnly,
+ stencilReadOnly,
+ });
+ });
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
new file mode 100644
index 0000000000..71741b63c9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_open_state.spec.js
@@ -0,0 +1,572 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests to all commands of GPUCommandEncoder, GPUComputePassEncoder, and
+GPURenderPassEncoder when the encoder is not finished.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { keysOf } from '../../../../common/util/data_tables.js';
+import { unreachable } from '../../../../common/util/util.js';
+import { ValidationTest } from '../validation_test.js';
+
+import { beginRenderPassWithQuerySet } from './queries/common.js';
+
+class F extends ValidationTest {
+ createRenderPipelineForTest() {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `@fragment fn main() {}`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ });
+ }
+
+ createBindGroupForTest() {
+ return this.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: this.device.createSampler(),
+ },
+ ],
+
+ layout: this.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ sampler: { type: 'filtering' },
+ },
+ ],
+ }),
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kEncoderCommandInfo = {
+ beginComputePass: {},
+ beginRenderPass: {},
+ clearBuffer: {},
+ copyBufferToBuffer: {},
+ copyBufferToTexture: {},
+ copyTextureToBuffer: {},
+ copyTextureToTexture: {},
+ insertDebugMarker: {},
+ popDebugGroup: {},
+ pushDebugGroup: {},
+ writeTimestamp: {},
+ resolveQuerySet: {},
+};
+const kEncoderCommands = keysOf(kEncoderCommandInfo);
+
+const kRenderPassEncoderCommandInfo = {
+ draw: {},
+ drawIndexed: {},
+ drawIndexedIndirect: {},
+ drawIndirect: {},
+ setIndexBuffer: {},
+ setBindGroup: {},
+ setVertexBuffer: {},
+ setPipeline: {},
+ setViewport: {},
+ setScissorRect: {},
+ setBlendConstant: {},
+ setStencilReference: {},
+ beginOcclusionQuery: {},
+ endOcclusionQuery: {},
+ executeBundles: {},
+ pushDebugGroup: {},
+ popDebugGroup: {},
+ insertDebugMarker: {},
+};
+const kRenderPassEncoderCommands = keysOf(kRenderPassEncoderCommandInfo);
+
+const kRenderBundleEncoderCommandInfo = {
+ draw: {},
+ drawIndexed: {},
+ drawIndexedIndirect: {},
+ drawIndirect: {},
+ setPipeline: {},
+ setBindGroup: {},
+ setIndexBuffer: {},
+ setVertexBuffer: {},
+ pushDebugGroup: {},
+ popDebugGroup: {},
+ insertDebugMarker: {},
+};
+const kRenderBundleEncoderCommands = keysOf(kRenderBundleEncoderCommandInfo);
+
+// MAINTENANCE_TODO: remove the deprecated 'dispatch' and 'dispatchIndirect' here once they're
+// removed from `@webgpu/types`.
+
+const kComputePassEncoderCommandInfo = {
+ setBindGroup: {},
+ setPipeline: {},
+ dispatchWorkgroups: {},
+ dispatchWorkgroupsIndirect: {},
+ pushDebugGroup: {},
+ popDebugGroup: {},
+ insertDebugMarker: {},
+};
+const kComputePassEncoderCommands = keysOf(kComputePassEncoderCommandInfo);
+
+g.test('non_pass_commands')
+ .desc(
+ `
+ Test that functions of GPUCommandEncoder generate a validation error if the encoder is already
+ finished.
+ `
+ )
+ .params(u =>
+ u
+ .combine('command', kEncoderCommands)
+ .beginSubcases()
+ .combine('finishBeforeCommand', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ switch (t.params.command) {
+ case 'writeTimestamp':
+ t.selectDeviceOrSkipTestCase('timestamp-query');
+ break;
+ }
+ })
+ .fn(t => {
+ const { command, finishBeforeCommand } = t.params;
+
+ const srcBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+ const dstBuffer = t.device.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.QUERY_RESOLVE,
+ });
+
+ const textureSize = { width: 1, height: 1 };
+ const textureFormat = 'rgba8unorm';
+ const srcTexture = t.device.createTexture({
+ size: textureSize,
+ format: textureFormat,
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+ const dstTexture = t.device.createTexture({
+ size: textureSize,
+ format: textureFormat,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const querySet = t.device.createQuerySet({
+ type: command === 'writeTimestamp' ? 'timestamp' : 'occlusion',
+ count: 1,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+
+ if (finishBeforeCommand) encoder.finish();
+
+ t.expectValidationError(() => {
+ switch (command) {
+ case 'beginComputePass':
+ {
+ encoder.beginComputePass();
+ }
+ break;
+ case 'beginRenderPass':
+ {
+ encoder.beginRenderPass({ colorAttachments: [] });
+ }
+ break;
+ case 'clearBuffer':
+ {
+ encoder.clearBuffer(dstBuffer, 0, 16);
+ }
+ break;
+ case 'copyBufferToBuffer':
+ {
+ encoder.copyBufferToBuffer(srcBuffer, 0, dstBuffer, 0, 0);
+ }
+ break;
+ case 'copyBufferToTexture':
+ {
+ encoder.copyBufferToTexture(
+ { buffer: srcBuffer },
+ { texture: dstTexture },
+ textureSize
+ );
+ }
+ break;
+ case 'copyTextureToBuffer':
+ {
+ encoder.copyTextureToBuffer(
+ { texture: srcTexture },
+ { buffer: dstBuffer },
+ textureSize
+ );
+ }
+ break;
+ case 'copyTextureToTexture':
+ {
+ encoder.copyTextureToTexture(
+ { texture: srcTexture },
+ { texture: dstTexture },
+ textureSize
+ );
+ }
+ break;
+ case 'insertDebugMarker':
+ {
+ encoder.insertDebugMarker('marker');
+ }
+ break;
+ case 'pushDebugGroup':
+ {
+ encoder.pushDebugGroup('group');
+ }
+ break;
+ case 'popDebugGroup':
+ {
+ encoder.popDebugGroup();
+ }
+ break;
+ case 'writeTimestamp':
+ {
+ encoder.writeTimestamp(querySet, 0);
+ }
+ break;
+ case 'resolveQuerySet':
+ {
+ encoder.resolveQuerySet(querySet, 0, 1, dstBuffer, 0);
+ }
+ break;
+ default:
+ unreachable();
+ }
+ }, finishBeforeCommand);
+ });
+
+g.test('render_pass_commands')
+ .desc(
+ `
+ Test that functions of GPURenderPassEncoder generate a validation error if the encoder or the
+ pass is already finished.
+
+ - TODO: Consider testing: nothing before command, end before command, end+finish before command.
+ `
+ )
+ .params(u =>
+ u
+ .combine('command', kRenderPassEncoderCommands)
+ .beginSubcases()
+ .combine('finishBeforeCommand', [false, true])
+ )
+ .fn(t => {
+ const { command, finishBeforeCommand } = t.params;
+
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: 1 });
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = beginRenderPassWithQuerySet(t, encoder, querySet);
+
+ const buffer = t.device.createBuffer({
+ size: 12,
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.VERTEX,
+ });
+
+ const pipeline = t.createRenderPipelineForTest();
+
+ const bindGroup = t.createBindGroupForTest();
+
+ if (finishBeforeCommand) {
+ renderPass.end();
+ encoder.finish();
+ }
+
+ t.expectValidationError(() => {
+ switch (command) {
+ case 'draw':
+ {
+ renderPass.draw(1);
+ }
+ break;
+ case 'drawIndexed':
+ {
+ renderPass.drawIndexed(1);
+ }
+ break;
+ case 'drawIndirect':
+ {
+ renderPass.drawIndirect(buffer, 1);
+ }
+ break;
+ case 'setIndexBuffer':
+ {
+ renderPass.setIndexBuffer(buffer, 'uint32');
+ }
+ break;
+ case 'drawIndexedIndirect':
+ {
+ renderPass.drawIndexedIndirect(buffer, 0);
+ }
+ break;
+ case 'setBindGroup':
+ {
+ renderPass.setBindGroup(0, bindGroup);
+ }
+ break;
+ case 'setVertexBuffer':
+ {
+ renderPass.setVertexBuffer(1, buffer);
+ }
+ break;
+ case 'setPipeline':
+ {
+ renderPass.setPipeline(pipeline);
+ }
+ break;
+ case 'setViewport':
+ {
+ const kNumTestPoints = 8;
+ const kViewportMinDepth = 0;
+ const kViewportMaxDepth = 1;
+ renderPass.setViewport(0, 0, kNumTestPoints, 0, kViewportMinDepth, kViewportMaxDepth);
+ }
+ break;
+ case 'setScissorRect':
+ {
+ renderPass.setScissorRect(0, 0, 0, 0);
+ }
+ break;
+ case 'setBlendConstant':
+ {
+ renderPass.setBlendConstant({ r: 1.0, g: 1.0, b: 1.0, a: 1.0 });
+ }
+ break;
+ case 'setStencilReference':
+ {
+ renderPass.setStencilReference(0);
+ }
+ break;
+ case 'beginOcclusionQuery':
+ {
+ renderPass.beginOcclusionQuery(0);
+ }
+ break;
+ case 'endOcclusionQuery':
+ {
+ renderPass.endOcclusionQuery();
+ }
+ break;
+ case 'executeBundles':
+ {
+ renderPass.executeBundles([]);
+ }
+ break;
+ case 'pushDebugGroup':
+ {
+ encoder.pushDebugGroup('group');
+ }
+ break;
+ case 'popDebugGroup':
+ {
+ encoder.popDebugGroup();
+ }
+ break;
+ case 'insertDebugMarker':
+ {
+ encoder.insertDebugMarker('marker');
+ }
+ break;
+ default:
+ unreachable();
+ }
+ }, finishBeforeCommand);
+ });
+
+g.test('render_bundle_commands')
+ .desc(
+ `
+ Test that functions of GPURenderBundleEncoder generate a validation error if the encoder or the
+ pass is already finished.
+ `
+ )
+ .params(u =>
+ u
+ .combine('command', kRenderBundleEncoderCommands)
+ .beginSubcases()
+ .combine('finishBeforeCommand', [false, true])
+ )
+ .fn(t => {
+ const { command, finishBeforeCommand } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 12,
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.VERTEX,
+ });
+
+ const pipeline = t.createRenderPipelineForTest();
+
+ const bindGroup = t.createBindGroupForTest();
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ });
+
+ if (finishBeforeCommand) {
+ bundleEncoder.finish();
+ }
+
+ t.expectValidationError(() => {
+ switch (command) {
+ case 'draw':
+ {
+ bundleEncoder.draw(1);
+ }
+ break;
+ case 'drawIndexed':
+ {
+ bundleEncoder.drawIndexed(1);
+ }
+ break;
+ case 'drawIndexedIndirect':
+ {
+ bundleEncoder.drawIndexedIndirect(buffer, 0);
+ }
+ break;
+ case 'drawIndirect':
+ {
+ bundleEncoder.drawIndirect(buffer, 1);
+ }
+ break;
+ case 'setPipeline':
+ {
+ bundleEncoder.setPipeline(pipeline);
+ }
+ break;
+ case 'setBindGroup':
+ {
+ bundleEncoder.setBindGroup(0, bindGroup);
+ }
+ break;
+ case 'setIndexBuffer':
+ {
+ bundleEncoder.setIndexBuffer(buffer, 'uint32');
+ }
+ break;
+ case 'setVertexBuffer':
+ {
+ bundleEncoder.setVertexBuffer(1, buffer);
+ }
+ break;
+ case 'pushDebugGroup':
+ {
+ bundleEncoder.pushDebugGroup('group');
+ }
+ break;
+ case 'popDebugGroup':
+ {
+ bundleEncoder.popDebugGroup();
+ }
+ break;
+ case 'insertDebugMarker':
+ {
+ bundleEncoder.insertDebugMarker('marker');
+ }
+ break;
+ default:
+ unreachable();
+ }
+ }, finishBeforeCommand);
+ });
+
+g.test('compute_pass_commands')
+ .desc(
+ `
+ Test that functions of GPUComputePassEncoder generate a validation error if the encoder or the
+ pass is already finished.
+
+ - TODO: Consider testing: nothing before command, end before command, end+finish before command.
+ `
+ )
+ .params(u =>
+ u
+ .combine('command', kComputePassEncoderCommands)
+ .beginSubcases()
+ .combine('finishBeforeCommand', [false, true])
+ )
+ .fn(t => {
+ const { command, finishBeforeCommand } = t.params;
+
+ const encoder = t.device.createCommandEncoder();
+ const computePass = encoder.beginComputePass();
+
+ const indirectBuffer = t.device.createBuffer({
+ size: 12,
+ usage: GPUBufferUsage.INDIRECT,
+ });
+
+ const computePipeline = t.createNoOpComputePipeline();
+
+ const bindGroup = t.createBindGroupForTest();
+
+ if (finishBeforeCommand) {
+ computePass.end();
+ encoder.finish();
+ }
+
+ t.expectValidationError(() => {
+ switch (command) {
+ case 'setBindGroup':
+ {
+ computePass.setBindGroup(0, bindGroup);
+ }
+ break;
+ case 'setPipeline':
+ {
+ computePass.setPipeline(computePipeline);
+ }
+ break;
+ case 'dispatchWorkgroups':
+ {
+ computePass.dispatchWorkgroups(0);
+ }
+ break;
+ case 'dispatchWorkgroupsIndirect':
+ {
+ computePass.dispatchWorkgroupsIndirect(indirectBuffer, 0);
+ }
+ break;
+ case 'pushDebugGroup':
+ {
+ computePass.pushDebugGroup('group');
+ }
+ break;
+ case 'popDebugGroup':
+ {
+ computePass.popDebugGroup();
+ }
+ break;
+ case 'insertDebugMarker':
+ {
+ computePass.insertDebugMarker('marker');
+ }
+ break;
+ default:
+ unreachable();
+ }
+ }, finishBeforeCommand);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_state.spec.js
new file mode 100644
index 0000000000..7d1c9cf0e6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/encoder_state.spec.js
@@ -0,0 +1,205 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- createCommandEncoder
+- non-pass command, or beginPass, during {render, compute} pass
+- {before (control case), after} finish()
+ - x= {finish(), ... all non-pass commands}
+- {before (control case), after} end()
+ - x= {render, compute} pass
+ - x= {finish(), ... all relevant pass commands}
+ - x= {
+ - before endPass (control case)
+ - after endPass (no pass open)
+ - after endPass+beginPass (a new pass of the same type is open)
+ - }
+ - should make whole encoder invalid
+- ?
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { objectEquals } from '../../../../common/util/util.js';
+import { ValidationTest } from '../validation_test.js';
+
+class F extends ValidationTest {
+ beginRenderPass(commandEncoder, view) {
+ return commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view,
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+
+ createAttachmentTextureView() {
+ const texture = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ this.trackForCleanup(texture);
+ return texture.createView();
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('pass_end_invalid_order')
+ .desc(
+ `
+ Test that beginning a {compute,render} pass before ending the previous {compute,render} pass
+ causes an error.
+
+ TODO: Update this test according to https://github.com/gpuweb/gpuweb/issues/2464
+ `
+ )
+ .params(u =>
+ u
+ .combine('pass0Type', ['compute', 'render'])
+ .combine('pass1Type', ['compute', 'render'])
+ .beginSubcases()
+ .combine('firstPassEnd', [true, false])
+ .combine('endPasses', [[], [0], [1], [0, 1], [1, 0]])
+ )
+ .fn(async t => {
+ const { pass0Type, pass1Type, firstPassEnd, endPasses } = t.params;
+
+ const view = t.createAttachmentTextureView();
+ const encoder = t.device.createCommandEncoder();
+
+ const firstPass =
+ pass0Type === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder, view);
+
+ if (firstPassEnd) firstPass.end();
+
+ // Begin a second pass before ending the previous pass.
+ const secondPass =
+ pass1Type === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder, view);
+
+ const passes = [firstPass, secondPass];
+ for (const index of endPasses) {
+ passes[index].end();
+ }
+
+ // If {endPasses} is '[1]' and {firstPass} ends, it's a control case.
+ const valid = firstPassEnd && objectEquals(endPasses, [1]);
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !valid);
+ });
+
+g.test('call_after_successful_finish')
+ .desc(`Test that encoding command after a successful finish generates a validation error.`)
+ .params(u =>
+ u
+ .combine('callCmd', ['beginComputePass', 'beginRenderPass', 'insertDebugMarker'])
+ .beginSubcases()
+ .combine('prePassType', ['compute', 'render', 'no-op'])
+ .combine('IsEncoderFinished', [false, true])
+ )
+ .fn(async t => {
+ const { prePassType, IsEncoderFinished, callCmd } = t.params;
+
+ const view = t.createAttachmentTextureView();
+ const encoder = t.device.createCommandEncoder();
+
+ if (prePassType !== 'no-op') {
+ const pass =
+ prePassType === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder, view);
+ pass.end();
+ }
+
+ if (IsEncoderFinished) {
+ encoder.finish();
+ }
+
+ switch (callCmd) {
+ case 'beginComputePass':
+ {
+ let pass;
+ t.expectValidationError(() => {
+ pass = encoder.beginComputePass();
+ }, IsEncoderFinished);
+ t.expectValidationError(() => {
+ pass.end();
+ }, IsEncoderFinished);
+ }
+ break;
+ case 'beginRenderPass':
+ {
+ let pass;
+ t.expectValidationError(() => {
+ pass = t.beginRenderPass(encoder, view);
+ }, IsEncoderFinished);
+ t.expectValidationError(() => {
+ pass.end();
+ }, IsEncoderFinished);
+ }
+ break;
+ case 'insertDebugMarker':
+ t.expectValidationError(() => {
+ encoder.insertDebugMarker('');
+ }, IsEncoderFinished);
+ break;
+ }
+
+ if (!IsEncoderFinished) {
+ encoder.finish();
+ }
+ });
+
+g.test('pass_end_none')
+ .desc(
+ `
+ Test that ending a {compute,render} pass without ending the passes generates a validation error.
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('passType', ['compute', 'render']).combine('endCount', [0, 1]))
+ .fn(async t => {
+ const { passType, endCount } = t.params;
+
+ const view = t.createAttachmentTextureView();
+ const encoder = t.device.createCommandEncoder();
+
+ const pass =
+ passType === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder, view);
+
+ for (let i = 0; i < endCount; ++i) {
+ pass.end();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, endCount === 0);
+ });
+
+g.test('pass_end_twice')
+ .desc('Test that ending a {compute,render} pass twice generates a validation error.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('passType', ['compute', 'render'])
+ .combine('endTwice', [false, true])
+ )
+ .fn(async t => {
+ const { passType, endTwice } = t.params;
+
+ const view = t.createAttachmentTextureView();
+ const encoder = t.device.createCommandEncoder();
+
+ const pass =
+ passType === 'compute' ? encoder.beginComputePass() : t.beginRenderPass(encoder, view);
+
+ pass.end();
+ if (endTwice) {
+ t.expectValidationError(() => {
+ pass.end();
+ });
+ }
+
+ encoder.finish();
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js
new file mode 100644
index 0000000000..25fdeebb0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/programmable/pipeline_bind_group_compat.spec.js
@@ -0,0 +1,757 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- test compatibility between bind groups and pipelines
+ - the binding resource in bindGroups[i].layout is "group-equivalent" (value-equal) to pipelineLayout.bgls[i].
+ - in the test fn, test once without the dispatch/draw (should always be valid) and once with
+ the dispatch/draw, to make sure the validation happens in dispatch/draw.
+ - x= {dispatch, all draws} (dispatch/draw should be size 0 to make sure validation still happens if no-op)
+ - x= all relevant stages
+
+TODO: subsume existing test, rewrite fixture as needed.
+TODO: Add externalTexture to kResourceTypes [1]
+`;
+import { kUnitCaseParamsBuilder } from '../../../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { memcpy, unreachable } from '../../../../../common/util/util.js';
+import {
+ kSamplerBindingTypes,
+ kShaderStageCombinations,
+ kBufferBindingTypes,
+} from '../../../../capability_info.js';
+import { GPUConst } from '../../../../constants.js';
+import { kProgrammableEncoderTypes } from '../../../../util/command_buffer_maker.js';
+import { ValidationTest } from '../../validation_test.js';
+
+const kComputeCmds = ['dispatch', 'dispatchIndirect'];
+
+const kRenderCmds = ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect'];
+
+// Test resource type compatibility in pipeline and bind group
+// [1]: Need to add externalTexture
+const kResourceTypes = ['uniformBuf', 'filtSamp', 'sampledTex', 'storageTex'];
+
+function getTestCmds(encoderType) {
+ return encoderType === 'compute pass' ? kComputeCmds : kRenderCmds;
+}
+
+const kCompatTestParams = kUnitCaseParamsBuilder
+ .combine('encoderType', kProgrammableEncoderTypes)
+ .expand('call', p => getTestCmds(p.encoderType))
+ .combine('callWithZero', [true, false]);
+
+class F extends ValidationTest {
+ getIndexBuffer() {
+ return this.device.createBuffer({
+ size: 8 * Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.INDEX,
+ });
+ }
+
+ getIndirectBuffer(indirectParams) {
+ const buffer = this.device.createBuffer({
+ mappedAtCreation: true,
+ size: indirectParams.length * Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST,
+ });
+ memcpy({ src: new Uint32Array(indirectParams) }, { dst: buffer.getMappedRange() });
+ buffer.unmap();
+ return buffer;
+ }
+
+ getBindingResourceType(entry) {
+ if (entry.buffer !== undefined) return 'uniformBuf';
+ if (entry.sampler !== undefined) return 'filtSamp';
+ if (entry.texture !== undefined) return 'sampledTex';
+ if (entry.storageTexture !== undefined) return 'storageTex';
+ unreachable();
+ }
+
+ createRenderPipelineWithLayout(bindGroups) {
+ const shader = `
+ @vertex fn vs_main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(1.0, 1.0, 0.0, 1.0);
+ }
+
+ @fragment fn fs_main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }
+ `;
+ const module = this.device.createShaderModule({ code: shader });
+ const pipeline = this.device.createRenderPipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: bindGroups.map(entries => this.device.createBindGroupLayout({ entries })),
+ }),
+ vertex: {
+ module,
+ entryPoint: 'vs_main',
+ },
+ fragment: {
+ module,
+ entryPoint: 'fs_main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ return pipeline;
+ }
+
+ createComputePipelineWithLayout(bindGroups) {
+ const shader = `
+ @compute @workgroup_size(1)
+ fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {
+ }
+ `;
+
+ const module = this.device.createShaderModule({ code: shader });
+ const pipeline = this.device.createComputePipeline({
+ layout: this.device.createPipelineLayout({
+ bindGroupLayouts: bindGroups.map(entries => this.device.createBindGroupLayout({ entries })),
+ }),
+ compute: {
+ module,
+ entryPoint: 'main',
+ },
+ });
+ return pipeline;
+ }
+
+ createBindGroupWithLayout(bglEntries) {
+ const bgEntries = [];
+ for (const entry of bglEntries) {
+ const resource = this.getBindingResource(this.getBindingResourceType(entry));
+ bgEntries.push({
+ binding: entry.binding,
+ resource,
+ });
+ }
+
+ return this.device.createBindGroup({
+ entries: bgEntries,
+ layout: this.device.createBindGroupLayout({ entries: bglEntries }),
+ });
+ }
+
+ doCompute(pass, call, callWithZero) {
+ const x = callWithZero ? 0 : 1;
+ switch (call) {
+ case 'dispatch':
+ pass.dispatchWorkgroups(x, 1, 1);
+ break;
+ case 'dispatchIndirect':
+ pass.dispatchWorkgroupsIndirect(this.getIndirectBuffer([x, 1, 1]), 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ doRender(pass, call, callWithZero) {
+ const vertexCount = callWithZero ? 0 : 3;
+ switch (call) {
+ case 'draw':
+ pass.draw(vertexCount, 1, 0, 0);
+ break;
+ case 'drawIndexed':
+ pass.setIndexBuffer(this.getIndexBuffer(), 'uint32');
+ pass.drawIndexed(vertexCount, 1, 0, 0, 0);
+ break;
+ case 'drawIndirect':
+ pass.drawIndirect(this.getIndirectBuffer([vertexCount, 1, 0, 0, 0]), 0);
+ break;
+ case 'drawIndexedIndirect':
+ pass.setIndexBuffer(this.getIndexBuffer(), 'uint32');
+ pass.drawIndexedIndirect(this.getIndirectBuffer([vertexCount, 1, 0, 0, 0]), 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ createBindGroupLayoutEntry(encoderType, resourceType, useU32Array) {
+ const entry = {
+ binding: 0,
+ visibility: encoderType === 'compute pass' ? GPUShaderStage.COMPUTE : GPUShaderStage.FRAGMENT,
+ };
+
+ switch (resourceType) {
+ case 'uniformBuf':
+ entry.buffer = { hasDynamicOffset: useU32Array }; // default type: uniform
+ break;
+ case 'filtSamp':
+ entry.sampler = {}; // default type: filtering
+ break;
+ case 'sampledTex':
+ entry.texture = {}; // default sampleType: float
+ break;
+ case 'storageTex':
+ entry.storageTexture = { access: 'write-only', format: 'rgba8unorm' };
+ break;
+ }
+
+ return entry;
+ }
+
+ runTest(encoderType, pipeline, bindGroups, dynamicOffsets, call, callWithZero, success) {
+ const { encoder, validateFinish } = this.createEncoder(encoderType);
+
+ if (encoder instanceof GPUComputePassEncoder) {
+ encoder.setPipeline(pipeline);
+ } else {
+ encoder.setPipeline(pipeline);
+ }
+
+ for (let i = 0; i < bindGroups.length; i++) {
+ const bindGroup = bindGroups[i];
+ if (!bindGroup) {
+ break;
+ }
+ if (dynamicOffsets) {
+ encoder.setBindGroup(
+ i,
+ bindGroup,
+ new Uint32Array(dynamicOffsets),
+ 0,
+ dynamicOffsets.length
+ );
+ } else {
+ encoder.setBindGroup(i, bindGroup);
+ }
+ }
+
+ if (encoder instanceof GPUComputePassEncoder) {
+ this.doCompute(encoder, call, callWithZero);
+ } else {
+ this.doRender(encoder, call, callWithZero);
+ }
+
+ validateFinish(success);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('bind_groups_and_pipeline_layout_mismatch')
+ .desc(
+ `
+ Tests the bind groups must match the requirements of the pipeline layout.
+ - bind groups required by the pipeline layout are required.
+ - bind groups unused by the pipeline layout can be set or not.
+ `
+ )
+ .params(
+ kCompatTestParams
+ .beginSubcases()
+ .combineWithParams([
+ { setBindGroup0: true, setBindGroup1: true, setUnusedBindGroup2: true, _success: true },
+ { setBindGroup0: true, setBindGroup1: true, setUnusedBindGroup2: false, _success: true },
+ { setBindGroup0: true, setBindGroup1: false, setUnusedBindGroup2: true, _success: false },
+ { setBindGroup0: false, setBindGroup1: true, setUnusedBindGroup2: true, _success: false },
+ { setBindGroup0: false, setBindGroup1: false, setUnusedBindGroup2: false, _success: false },
+ ])
+ .combine('useU32Array', [false, true])
+ )
+ .fn(t => {
+ const {
+ encoderType,
+ call,
+ callWithZero,
+ setBindGroup0,
+ setBindGroup1,
+ setUnusedBindGroup2,
+ _success,
+ useU32Array,
+ } = t.params;
+ const visibility =
+ encoderType === 'compute pass' ? GPUShaderStage.COMPUTE : GPUShaderStage.VERTEX;
+
+ const bindGroupLayouts = [
+ // bind group layout 0
+ [
+ {
+ binding: 0,
+ visibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ },
+ ],
+
+ // bind group layout 1
+ [
+ {
+ binding: 0,
+ visibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ },
+ ],
+ ];
+
+ // Create required bind groups
+ const bindGroup0 = setBindGroup0 ? t.createBindGroupWithLayout(bindGroupLayouts[0]) : undefined;
+ const bindGroup1 = setBindGroup1 ? t.createBindGroupWithLayout(bindGroupLayouts[1]) : undefined;
+ const unusedBindGroup2 = setUnusedBindGroup2
+ ? t.createBindGroupWithLayout(bindGroupLayouts[1])
+ : undefined;
+
+ // Create fixed pipeline
+ const pipeline =
+ encoderType === 'compute pass'
+ ? t.createComputePipelineWithLayout(bindGroupLayouts)
+ : t.createRenderPipelineWithLayout(bindGroupLayouts);
+
+ const dynamicOffsets = useU32Array ? [0] : undefined;
+
+ // Test without the dispatch/draw (should always be valid)
+ t.runTest(
+ encoderType,
+ pipeline,
+ [bindGroup0, bindGroup1, unusedBindGroup2],
+ dynamicOffsets,
+ undefined,
+ false,
+ true
+ );
+
+ // Test with the dispatch/draw, to make sure the validation happens in dispatch/draw.
+ t.runTest(
+ encoderType,
+ pipeline,
+ [bindGroup0, bindGroup1, unusedBindGroup2],
+ dynamicOffsets,
+ call,
+ callWithZero,
+ _success
+ );
+ });
+
+g.test('buffer_binding,render_pipeline')
+ .desc(
+ `
+ The GPUBufferBindingLayout bindings configure should be exactly
+ same in PipelineLayout and bindgroup.
+ - TODO: test more draw functions, e.g. indirect
+ - TODO: test more visibilities, e.g. vertex
+ - TODO: bind group should be created with different layout
+ `
+ )
+ .params(u => u.combine('type', kBufferBindingTypes))
+ .fn(async t => {
+ const { type } = t.params;
+
+ // Create fixed bindGroup
+ const uniformBuffer = t.getUniformBuffer();
+
+ const bindGroup = t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+
+ layout: t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ buffer: {}, // default type: uniform
+ },
+ ],
+ }),
+ });
+
+ // Create pipeline with different layouts
+ const pipeline = t.createRenderPipelineWithLayout([
+ [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ buffer: {
+ type,
+ },
+ },
+ ],
+ ]);
+
+ const { encoder, validateFinish } = t.createEncoder('render pass');
+ encoder.setPipeline(pipeline);
+ encoder.setBindGroup(0, bindGroup);
+ encoder.draw(3);
+
+ validateFinish(type === undefined || type === 'uniform');
+ });
+
+g.test('sampler_binding,render_pipeline')
+ .desc(
+ `
+ The GPUSamplerBindingLayout bindings configure should be exactly
+ same in PipelineLayout and bindgroup.
+ - TODO: test more draw functions, e.g. indirect
+ - TODO: test more visibilities, e.g. vertex
+ `
+ )
+ .params(u =>
+ u //
+ .combine('bglType', kSamplerBindingTypes)
+ .combine('bgType', kSamplerBindingTypes)
+ )
+ .fn(async t => {
+ const { bglType, bgType } = t.params;
+ const bindGroup = t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource:
+ bgType === 'comparison'
+ ? t.device.createSampler({ compare: 'always' })
+ : t.device.createSampler(),
+ },
+ ],
+
+ layout: t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ sampler: { type: bgType },
+ },
+ ],
+ }),
+ });
+
+ // Create pipeline with different layouts
+ const pipeline = t.createRenderPipelineWithLayout([
+ [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ sampler: {
+ type: bglType,
+ },
+ },
+ ],
+ ]);
+
+ const { encoder, validateFinish } = t.createEncoder('render pass');
+ encoder.setPipeline(pipeline);
+ encoder.setBindGroup(0, bindGroup);
+ encoder.draw(3);
+
+ validateFinish(bglType === bgType);
+ });
+
+g.test('bgl_binding_mismatch')
+ .desc(
+ 'Tests the binding number must exist or not exist in both bindGroups[i].layout and pipelineLayout.bgls[i]'
+ )
+ .params(
+ kCompatTestParams
+ .beginSubcases()
+ .combineWithParams([
+ { bgBindings: [0, 1, 2], plBindings: [0, 1, 2], _success: true },
+ { bgBindings: [0, 1, 2], plBindings: [0, 1, 3], _success: false },
+ { bgBindings: [0, 2], plBindings: [0, 2], _success: true },
+ { bgBindings: [0, 2], plBindings: [2, 0], _success: true },
+ { bgBindings: [0, 1, 2], plBindings: [0, 1], _success: false },
+ { bgBindings: [0, 1], plBindings: [0, 1, 2], _success: false },
+ ])
+ .combine('useU32Array', [false, true])
+ )
+ .fn(t => {
+ const {
+ encoderType,
+ call,
+ callWithZero,
+ bgBindings,
+ plBindings,
+ _success,
+ useU32Array,
+ } = t.params;
+ const visibility =
+ encoderType === 'compute pass' ? GPUShaderStage.COMPUTE : GPUShaderStage.VERTEX;
+
+ const bglEntries = [];
+ for (const binding of bgBindings) {
+ bglEntries.push({
+ binding,
+ visibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ });
+ }
+ const bindGroup = t.createBindGroupWithLayout(bglEntries);
+
+ const plEntries = [[]];
+ for (const binding of plBindings) {
+ plEntries[0].push({
+ binding,
+ visibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ });
+ }
+ const pipeline =
+ encoderType === 'compute pass'
+ ? t.createComputePipelineWithLayout(plEntries)
+ : t.createRenderPipelineWithLayout(plEntries);
+
+ const dynamicOffsets = useU32Array ? new Array(bgBindings.length).fill(0) : undefined;
+
+ // Test without the dispatch/draw (should always be valid)
+ t.runTest(encoderType, pipeline, [bindGroup], dynamicOffsets, undefined, false, true);
+
+ // Test with the dispatch/draw, to make sure the validation happens in dispatch/draw.
+ t.runTest(encoderType, pipeline, [bindGroup], dynamicOffsets, call, callWithZero, _success);
+ });
+
+g.test('bgl_visibility_mismatch')
+ .desc('Tests the visibility in bindGroups[i].layout and pipelineLayout.bgls[i] must be matched')
+ .params(
+ kCompatTestParams
+ .beginSubcases()
+ .combine('bgVisibility', kShaderStageCombinations)
+ .expand('plVisibility', p =>
+ p.encoderType === 'compute pass'
+ ? [GPUConst.ShaderStage.COMPUTE]
+ : [
+ GPUConst.ShaderStage.VERTEX,
+ GPUConst.ShaderStage.FRAGMENT,
+ GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT,
+ ]
+ )
+ .combine('useU32Array', [false, true])
+ )
+ .fn(t => {
+ const { encoderType, call, callWithZero, bgVisibility, plVisibility, useU32Array } = t.params;
+
+ const bglEntries = [
+ {
+ binding: 0,
+ visibility: bgVisibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ },
+ ];
+
+ const bindGroup = t.createBindGroupWithLayout(bglEntries);
+
+ const plEntries = [
+ [
+ {
+ binding: 0,
+ visibility: plVisibility,
+ buffer: { hasDynamicOffset: useU32Array }, // default type: uniform
+ },
+ ],
+ ];
+
+ const pipeline =
+ encoderType === 'compute pass'
+ ? t.createComputePipelineWithLayout(plEntries)
+ : t.createRenderPipelineWithLayout(plEntries);
+
+ const dynamicOffsets = useU32Array ? [0] : undefined;
+
+ // Test without the dispatch/draw (should always be valid)
+ t.runTest(encoderType, pipeline, [bindGroup], dynamicOffsets, undefined, false, true);
+
+ // Test with the dispatch/draw, to make sure the validation happens in dispatch/draw.
+ t.runTest(
+ encoderType,
+ pipeline,
+ [bindGroup],
+ dynamicOffsets,
+ call,
+ callWithZero,
+ bgVisibility === plVisibility
+ );
+ });
+
+g.test('bgl_resource_type_mismatch')
+ .desc(
+ `
+ Tests the binding resource type in bindGroups[i].layout and pipelineLayout.bgls[i] must be matched
+ - TODO: Test externalTexture
+ `
+ )
+ .params(
+ kCompatTestParams
+ .beginSubcases()
+ .combine('bgResourceType', kResourceTypes)
+ .combine('plResourceType', kResourceTypes)
+ .expand('useU32Array', p => (p.bgResourceType === 'uniformBuf' ? [true, false] : [false]))
+ )
+ .fn(t => {
+ const {
+ encoderType,
+ call,
+ callWithZero,
+ bgResourceType,
+ plResourceType,
+ useU32Array,
+ } = t.params;
+
+ const bglEntries = [t.createBindGroupLayoutEntry(encoderType, bgResourceType, useU32Array)];
+
+ const bindGroup = t.createBindGroupWithLayout(bglEntries);
+
+ const plEntries = [[t.createBindGroupLayoutEntry(encoderType, plResourceType, useU32Array)]];
+
+ const pipeline =
+ encoderType === 'compute pass'
+ ? t.createComputePipelineWithLayout(plEntries)
+ : t.createRenderPipelineWithLayout(plEntries);
+
+ const dynamicOffsets = useU32Array ? [0] : undefined;
+
+ // Test without the dispatch/draw (should always be valid)
+ t.runTest(encoderType, pipeline, [bindGroup], dynamicOffsets, undefined, false, true);
+
+ // Test with the dispatch/draw, to make sure the validation happens in dispatch/draw.
+ t.runTest(
+ encoderType,
+ pipeline,
+ [bindGroup],
+ dynamicOffsets,
+ call,
+ callWithZero,
+ bgResourceType === plResourceType
+ );
+ });
+
+g.test('empty_bind_group_layouts_requires_empty_bind_groups,compute_pass')
+ .desc(
+ `
+ Test that a compute pipeline with empty bind groups layouts requires empty bind groups to be set.
+ `
+ )
+ .params(u =>
+ u
+ .combine('bindGroupLayoutEntryCount', [3, 4])
+ .combine('computeCommand', ['dispatchIndirect', 'dispatch'])
+ )
+ .fn(async t => {
+ const { bindGroupLayoutEntryCount, computeCommand } = t.params;
+
+ const emptyBGLCount = 4;
+ const emptyBGL = t.device.createBindGroupLayout({ entries: [] });
+ const emptyBGLs = [];
+ for (let i = 0; i < emptyBGLCount; i++) {
+ emptyBGLs.push(emptyBGL);
+ }
+
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: emptyBGLs,
+ });
+
+ const pipeline = t.device.createComputePipeline({
+ layout: pipelineLayout,
+ compute: {
+ module: t.device.createShaderModule({
+ code: '@compute @workgroup_size(1) fn main() {}',
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const emptyBindGroup = t.device.createBindGroup({
+ layout: emptyBGL,
+ entries: [],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const computePass = encoder.beginComputePass();
+ computePass.setPipeline(pipeline);
+ for (let i = 0; i < bindGroupLayoutEntryCount; i++) {
+ computePass.setBindGroup(i, emptyBindGroup);
+ }
+
+ t.doCompute(computePass, computeCommand, true);
+ computePass.end();
+
+ const success = bindGroupLayoutEntryCount === emptyBGLCount;
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('empty_bind_group_layouts_requires_empty_bind_groups,render_pass')
+ .desc(
+ `
+ Test that a render pipeline with empty bind groups layouts requires empty bind groups to be set.
+ `
+ )
+ .params(u =>
+ u
+ .combine('bindGroupLayoutEntryCount', [3, 4])
+ .combine('renderCommand', ['draw', 'drawIndexed', 'drawIndirect', 'drawIndexedIndirect'])
+ )
+ .fn(async t => {
+ const { bindGroupLayoutEntryCount, renderCommand } = t.params;
+
+ const emptyBGLCount = 4;
+ const emptyBGL = t.device.createBindGroupLayout({ entries: [] });
+ const emptyBGLs = [];
+ for (let i = 0; i < emptyBGLCount; i++) {
+ emptyBGLs.push(emptyBGL);
+ }
+
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: emptyBGLs,
+ });
+
+ const colorFormat = 'rgba8unorm';
+ const pipeline = t.device.createRenderPipeline({
+ layout: pipelineLayout,
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `@vertex fn main() -> @builtin(position) vec4<f32> { return vec4<f32>(); }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() {}`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: colorFormat, writeMask: 0 }],
+ },
+ });
+
+ const emptyBindGroup = t.device.createBindGroup({
+ layout: emptyBGL,
+ entries: [],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+
+ const attachmentTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: attachmentTexture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+
+ renderPass.setPipeline(pipeline);
+ for (let i = 0; i < bindGroupLayoutEntryCount; i++) {
+ renderPass.setBindGroup(i, emptyBindGroup);
+ }
+ t.doRender(renderPass, renderCommand, true);
+ renderPass.end();
+
+ const success = bindGroupLayoutEntryCount === emptyBGLCount;
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/begin_end.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/begin_end.spec.js
new file mode 100644
index 0000000000..627ad081e2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/begin_end.spec.js
@@ -0,0 +1,163 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation for encoding begin/endable queries.
+
+TODO: pipeline statistics queries are removed from core; consider moving tests to another suite.
+TODO: tests for pipeline statistics queries:
+- balance: {
+ - begin 0, end 1
+ - begin 1, end 0
+ - begin 1, end 1
+ - begin 2, end 2
+ - }
+ - x= {
+ - render pass + pipeline statistics
+ - compute pass + pipeline statistics
+ - }
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+import { beginRenderPassWithQuerySet, createQuerySetWithType } from './common.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('occlusion_query,begin_end_balance')
+ .desc(
+ `
+Tests that begin/end occlusion queries mismatch on render pass:
+- begin n queries, then end m queries, for various n and m.
+ `
+ )
+ .paramsSubcasesOnly([
+ { begin: 0, end: 1 },
+ { begin: 1, end: 0 },
+ { begin: 1, end: 1 }, // control case
+ { begin: 1, end: 2 },
+ { begin: 2, end: 1 },
+ ])
+ .fn(async t => {
+ const { begin, end } = t.params;
+
+ const occlusionQuerySet = createQuerySetWithType(t, 'occlusion', 2);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ for (let i = 0; i < begin; i++) {
+ encoder.encoder.beginOcclusionQuery(i);
+ }
+ for (let j = 0; j < end; j++) {
+ encoder.encoder.endOcclusionQuery();
+ }
+ encoder.validateFinishAndSubmit(begin === end, true);
+ });
+
+g.test('occlusion_query,begin_end_invalid_nesting')
+ .desc(
+ `
+Tests the invalid nesting of begin/end occlusion queries:
+- begin index 0, end, begin index 0, end (control case)
+- begin index 0, begin index 0, end, end
+- begin index 0, begin index 1, end, end
+ `
+ )
+ .paramsSubcasesOnly([
+ { calls: [0, 'end', 1, 'end'], _valid: true }, // control case
+ { calls: [0, 0, 'end', 'end'], _valid: false },
+ { calls: [0, 1, 'end', 'end'], _valid: false },
+ ])
+ .fn(async t => {
+ const { calls, _valid } = t.params;
+
+ const occlusionQuerySet = createQuerySetWithType(t, 'occlusion', 2);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ for (const i of calls) {
+ if (i !== 'end') {
+ encoder.encoder.beginOcclusionQuery(i);
+ } else {
+ encoder.encoder.endOcclusionQuery();
+ }
+ }
+ encoder.validateFinishAndSubmit(_valid, true);
+ });
+
+g.test('occlusion_query,disjoint_queries_with_same_query_index')
+ .desc(
+ `
+Tests that two disjoint occlusion queries cannot be begun with same query index on same render pass:
+- begin index 0, end, begin index 0, end
+- call on {same (invalid), different (control case)} render pass
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('isOnSameRenderPass', [false, true]))
+ .fn(async t => {
+ const querySet = createQuerySetWithType(t, 'occlusion', 1);
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = beginRenderPassWithQuerySet(t, encoder, querySet);
+ pass.beginOcclusionQuery(0);
+ pass.endOcclusionQuery();
+
+ if (t.params.isOnSameRenderPass) {
+ pass.beginOcclusionQuery(0);
+ pass.endOcclusionQuery();
+ pass.end();
+ } else {
+ pass.end();
+ const otherPass = beginRenderPassWithQuerySet(t, encoder, querySet);
+ otherPass.beginOcclusionQuery(0);
+ otherPass.endOcclusionQuery();
+ otherPass.end();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, t.params.isOnSameRenderPass);
+ });
+
+g.test('nesting')
+ .desc(
+ `
+Tests that whether it's allowed to nest various types of queries:
+- call {occlusion, pipeline-statistics, timestamp} query in same type or other type.
+ `
+ )
+ .paramsSubcasesOnly([
+ { begin: 'occlusion', nest: 'timestamp', end: 'occlusion', _valid: true },
+ { begin: 'occlusion', nest: 'occlusion', end: 'occlusion', _valid: false },
+ { begin: 'occlusion', nest: 'pipeline-statistics', end: 'occlusion', _valid: true },
+ {
+ begin: 'occlusion',
+ nest: 'pipeline-statistics',
+ end: 'pipeline-statistics',
+ _valid: true,
+ },
+ {
+ begin: 'pipeline-statistics',
+ nest: 'timestamp',
+ end: 'pipeline-statistics',
+ _valid: true,
+ },
+ {
+ begin: 'pipeline-statistics',
+ nest: 'pipeline-statistics',
+ end: 'pipeline-statistics',
+ _valid: false,
+ },
+ {
+ begin: 'pipeline-statistics',
+ nest: 'occlusion',
+ end: 'pipeline-statistics',
+ _valid: true,
+ },
+ { begin: 'pipeline-statistics', nest: 'occlusion', end: 'occlusion', _valid: true },
+ { begin: 'timestamp', nest: 'occlusion', end: 'occlusion', _valid: true },
+ {
+ begin: 'timestamp',
+ nest: 'pipeline-statistics',
+ end: 'pipeline-statistics',
+ _valid: true,
+ },
+ ])
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/common.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/common.js
new file mode 100644
index 0000000000..4284b2a318
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/common.js
@@ -0,0 +1,30 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export function createQuerySetWithType(t, type, count) {
+ return t.device.createQuerySet({
+ type,
+ count,
+ });
+}
+
+export function beginRenderPassWithQuerySet(t, encoder, querySet) {
+ const view = t.device
+ .createTexture({
+ format: 'rgba8unorm',
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ })
+ .createView();
+ return encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view,
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ occlusionQuerySet: querySet,
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js
new file mode 100644
index 0000000000..43c7c037c9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/general.spec.js
@@ -0,0 +1,158 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO: pipeline statistics queries are removed from core; consider moving tests to another suite.
+TODO:
+- Start a pipeline statistics query in all possible encoders:
+ - queryIndex {in, out of} range for GPUQuerySet
+ - GPUQuerySet {valid, invalid, device mismatched}
+ - x ={render pass, compute pass} encoder
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { kQueryTypes } from '../../../../capability_info.js';
+import { ValidationTest } from '../../validation_test.js';
+
+import { createQuerySetWithType } from './common.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('occlusion_query,query_type')
+ .desc(
+ `
+Tests that set occlusion query set with all types in render pass descriptor:
+- type {occlusion (control case), pipeline statistics, timestamp}
+- {undefined} for occlusion query set in render pass descriptor
+ `
+ )
+ .params(u => u.combine('type', [undefined, ...kQueryTypes]))
+ .beforeAllSubcases(t => {
+ const { type } = t.params;
+ if (type) {
+ t.selectDeviceForQueryTypeOrSkipTestCase(type);
+ }
+ })
+ .fn(async t => {
+ const type = t.params.type;
+ const querySet = type === undefined ? undefined : createQuerySetWithType(t, type, 1);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet: querySet });
+ encoder.encoder.beginOcclusionQuery(0);
+ encoder.encoder.endOcclusionQuery();
+ encoder.validateFinish(type === 'occlusion');
+ });
+
+g.test('occlusion_query,invalid_query_set')
+ .desc(
+ `
+Tests that begin occlusion query with a invalid query set that failed during creation.
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('querySetState', ['valid', 'invalid']))
+ .fn(t => {
+ const occlusionQuerySet = t.createQuerySetWithState(t.params.querySetState);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ encoder.encoder.beginOcclusionQuery(0);
+ encoder.encoder.endOcclusionQuery();
+ encoder.validateFinishAndSubmitGivenState(t.params.querySetState);
+ });
+
+g.test('occlusion_query,query_index')
+ .desc(
+ `
+Tests that begin occlusion query with query index:
+- queryIndex {in, out of} range for GPUQuerySet
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('queryIndex', [0, 2]))
+ .fn(t => {
+ const occlusionQuerySet = createQuerySetWithType(t, 'occlusion', 2);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ encoder.encoder.beginOcclusionQuery(t.params.queryIndex);
+ encoder.encoder.endOcclusionQuery();
+ encoder.validateFinish(t.params.queryIndex < 2);
+ });
+
+g.test('timestamp_query,query_type_and_index')
+ .desc(
+ `
+Tests that write timestamp to all types of query set on all possible encoders:
+- type {occlusion, pipeline statistics, timestamp}
+- queryIndex {in, out of} range for GPUQuerySet
+- x= {non-pass} encoder
+ `
+ )
+ .params(u =>
+ u
+ .combine('type', kQueryTypes)
+ .beginSubcases()
+ .expand('queryIndex', p => (p.type === 'timestamp' ? [0, 2] : [0]))
+ )
+ .beforeAllSubcases(t => {
+ const { type } = t.params;
+
+ // writeTimestamp is only available for devices that enable the 'timestamp-query' feature.
+ const queryTypes = ['timestamp'];
+ if (type !== 'timestamp') {
+ queryTypes.push(type);
+ }
+
+ t.selectDeviceForQueryTypeOrSkipTestCase(queryTypes);
+ })
+ .fn(async t => {
+ const { type, queryIndex } = t.params;
+
+ const count = 2;
+ const querySet = createQuerySetWithType(t, type, count);
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.writeTimestamp(querySet, queryIndex);
+ encoder.validateFinish(type === 'timestamp' && queryIndex < count);
+ });
+
+g.test('timestamp_query,invalid_query_set')
+ .desc(
+ `
+Tests that write timestamp to a invalid query set that failed during creation:
+- x= {non-pass} encoder
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('querySetState', ['valid', 'invalid']))
+ .beforeAllSubcases(t => {
+ t.selectDeviceForQueryTypeOrSkipTestCase('timestamp');
+ })
+ .fn(async t => {
+ const { querySetState } = t.params;
+
+ const querySet = t.createQuerySetWithState(querySetState, {
+ type: 'timestamp',
+ count: 2,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.writeTimestamp(querySet, 0);
+ encoder.validateFinish(querySetState !== 'invalid');
+ });
+
+g.test('timestamp_query,device_mismatch')
+ .desc('Tests writeTimestamp cannot be called with a query set created from another device')
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceForQueryTypeOrSkipTestCase('timestamp');
+ t.selectMismatchedDeviceOrSkipTestCase('timestamp-query');
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const querySet = sourceDevice.createQuerySet({
+ type: 'timestamp',
+ count: 2,
+ });
+ t.trackForCleanup(querySet);
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.writeTimestamp(querySet, 0);
+ encoder.validateFinish(!mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/pipeline_statistics.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/pipeline_statistics.spec.js
new file mode 100644
index 0000000000..394c2beb0b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/pipeline_statistics.spec.js
@@ -0,0 +1,15 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation for encoding pipeline statistics queries.
+Excludes query begin/end balance and nesting (begin_end.spec.ts)
+and querySet/queryIndex (general.spec.ts).
+
+TODO: pipeline statistics queries are removed from core; consider moving tests to another suite.
+TODO:
+- Test pipelineStatistics with {undefined, empty, duplicated, full (control case)} values
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.js
new file mode 100644
index 0000000000..ed53a30aa1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.js
@@ -0,0 +1,183 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for resolveQuerySet.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../../constants.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+export const kQueryCount = 2;
+
+g.test('queryset_and_destination_buffer_state')
+ .desc(
+ `
+Tests that resolve query set must be with valid query set and destination buffer.
+- {invalid, destroyed} GPUQuerySet results in validation error.
+- {invalid, destroyed} destination buffer results in validation error.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('querySetState', kResourceStates)
+ .combine('destinationState', kResourceStates)
+ )
+ .fn(async t => {
+ const { querySetState, destinationState } = t.params;
+
+ const shouldBeValid = querySetState !== 'invalid' && destinationState !== 'invalid';
+ const shouldSubmitSuccess = querySetState === 'valid' && destinationState === 'valid';
+
+ const querySet = t.createQuerySetWithState(querySetState);
+
+ const destination = t.createBufferWithState(destinationState, {
+ size: kQueryCount * 8,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, 1, destination, 0);
+ encoder.validateFinishAndSubmit(shouldBeValid, shouldSubmitSuccess);
+ });
+
+g.test('first_query_and_query_count')
+ .desc(
+ `
+Tests that resolve query set with invalid firstQuery and queryCount:
+- firstQuery and/or queryCount out of range
+ `
+ )
+ .paramsSubcasesOnly([
+ { firstQuery: 0, queryCount: kQueryCount }, // control case
+ { firstQuery: 0, queryCount: kQueryCount + 1 },
+ { firstQuery: 1, queryCount: kQueryCount },
+ { firstQuery: kQueryCount, queryCount: 1 },
+ ])
+ .fn(async t => {
+ const { firstQuery, queryCount } = t.params;
+
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: kQueryCount });
+ const destination = t.device.createBuffer({
+ size: kQueryCount * 8,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, 0);
+ encoder.validateFinish(firstQuery + queryCount <= kQueryCount);
+ });
+
+g.test('destination_buffer_usage')
+ .desc(
+ `
+Tests that resolve query set with invalid destinationBuffer:
+- Buffer usage {with, without} QUERY_RESOLVE
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('bufferUsage', [
+ GPUConst.BufferUsage.STORAGE,
+ GPUConst.BufferUsage.QUERY_RESOLVE, // control case
+ ])
+ )
+ .fn(async t => {
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: kQueryCount });
+ const destination = t.device.createBuffer({
+ size: kQueryCount * 8,
+ usage: t.params.bufferUsage,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, destination, 0);
+ encoder.validateFinish(t.params.bufferUsage === GPUConst.BufferUsage.QUERY_RESOLVE);
+ });
+
+g.test('destination_offset_alignment')
+ .desc(
+ `
+Tests that resolve query set with invalid destinationOffset:
+- destinationOffset is not a multiple of 256
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('destinationOffset', [0, 128, 256, 384]))
+ .fn(async t => {
+ const { destinationOffset } = t.params;
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: kQueryCount });
+ const destination = t.device.createBuffer({
+ size: 512,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, destination, destinationOffset);
+ encoder.validateFinish(destinationOffset % 256 === 0);
+ });
+
+g.test('resolve_buffer_oob')
+ .desc(
+ `
+Tests that resolve query set with the size oob:
+- The size of destinationBuffer - destinationOffset < queryCount * 8
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u.combineWithParams([
+ { queryCount: 2, bufferSize: 16, destinationOffset: 0, _success: true },
+ { queryCount: 3, bufferSize: 16, destinationOffset: 0, _success: false },
+ { queryCount: 2, bufferSize: 16, destinationOffset: 256, _success: false },
+ { queryCount: 2, bufferSize: 272, destinationOffset: 256, _success: true },
+ { queryCount: 2, bufferSize: 264, destinationOffset: 256, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { queryCount, bufferSize, destinationOffset, _success } = t.params;
+ const querySet = t.device.createQuerySet({ type: 'occlusion', count: queryCount });
+ const destination = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, queryCount, destination, destinationOffset);
+ encoder.validateFinish(_success);
+ });
+
+g.test('query_set_buffer,device_mismatch')
+ .desc(
+ 'Tests resolveQuerySet cannot be called with a query set or destination buffer created from another device'
+ )
+ .paramsSubcasesOnly([
+ { querySetMismatched: false, bufferMismatched: false }, // control case
+ { querySetMismatched: true, bufferMismatched: false },
+ { querySetMismatched: false, bufferMismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { querySetMismatched, bufferMismatched } = t.params;
+
+ const kQueryCount = 1;
+
+ const querySetDevice = querySetMismatched ? t.mismatchedDevice : t.device;
+ const querySet = querySetDevice.createQuerySet({
+ type: 'occlusion',
+ count: kQueryCount,
+ });
+ t.trackForCleanup(querySet);
+
+ const bufferDevice = bufferMismatched ? t.mismatchedDevice : t.device;
+ const buffer = bufferDevice.createBuffer({
+ size: kQueryCount * 8,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+ t.trackForCleanup(buffer);
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, buffer, 0);
+ encoder.validateFinish(!(querySetMismatched || bufferMismatched));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js
new file mode 100644
index 0000000000..29e006dab0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/encoding/render_bundle.spec.js
@@ -0,0 +1,259 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests execution of render bundles.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kDepthStencilFormats, kTextureFormatInfo } from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('empty_bundle_list')
+ .desc(
+ `
+ Test that it is valid to execute an empty list of render bundles
+ `
+ )
+ .fn(async t => {
+ const encoder = t.createEncoder('render pass');
+ encoder.encoder.executeBundles([]);
+ encoder.validateFinish(true);
+ });
+
+g.test('device_mismatch')
+ .desc(
+ `
+ Tests executeBundles cannot be called with render bundles created from another device
+ Test with two bundles to make sure all bundles can be validated:
+ - bundle0 and bundle1 from same device
+ - bundle0 and bundle1 from different device
+ `
+ )
+ .paramsSubcasesOnly([
+ { bundle0Mismatched: false, bundle1Mismatched: false }, // control case
+ { bundle0Mismatched: true, bundle1Mismatched: false },
+ { bundle0Mismatched: false, bundle1Mismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { bundle0Mismatched, bundle1Mismatched } = t.params;
+
+ const descriptor = {
+ colorFormats: ['rgba8unorm'],
+ };
+
+ const bundle0Device = bundle0Mismatched ? t.mismatchedDevice : t.device;
+ const bundle0 = bundle0Device.createRenderBundleEncoder(descriptor).finish();
+
+ const bundle1Device = bundle1Mismatched ? t.mismatchedDevice : t.device;
+ const bundle1 = bundle1Device.createRenderBundleEncoder(descriptor).finish();
+
+ const encoder = t.createEncoder('render pass');
+ encoder.encoder.executeBundles([bundle0, bundle1]);
+
+ encoder.validateFinish(!(bundle0Mismatched || bundle1Mismatched));
+ });
+
+g.test('color_formats_mismatch')
+ .desc(
+ `
+ Tests executeBundles cannot be called with render bundles that do match the colorFormats of the
+ render pass. This includes:
+ - formats don't match
+ - formats match but are in a different order
+ - formats match but there is a different count
+ `
+ )
+ .params(u =>
+ u.combineWithParams([
+ {
+ bundleFormats: ['bgra8unorm', 'rg8unorm'],
+ passFormats: ['bgra8unorm', 'rg8unorm'],
+ _compatible: true,
+ }, // control case
+ {
+ bundleFormats: ['bgra8unorm', 'rg8unorm'],
+ passFormats: ['bgra8unorm', 'bgra8unorm'],
+ _compatible: false,
+ },
+ {
+ bundleFormats: ['bgra8unorm', 'rg8unorm'],
+ passFormats: ['rg8unorm', 'bgra8unorm'],
+ _compatible: false,
+ },
+ {
+ bundleFormats: ['bgra8unorm', 'rg8unorm', 'rgba8unorm'],
+ passFormats: ['rg8unorm', 'bgra8unorm'],
+ _compatible: false,
+ },
+ {
+ bundleFormats: ['bgra8unorm', 'rg8unorm'],
+ passFormats: ['rg8unorm', 'bgra8unorm', 'rgba8unorm'],
+ _compatible: false,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { bundleFormats, passFormats, _compatible } = t.params;
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: bundleFormats,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const encoder = t.createEncoder('render pass', {
+ attachmentInfo: {
+ colorFormats: passFormats,
+ },
+ });
+ encoder.encoder.executeBundles([bundle]);
+
+ encoder.validateFinish(_compatible);
+ });
+
+g.test('depth_stencil_formats_mismatch')
+ .desc(
+ `
+ Tests executeBundles cannot be called with render bundles that do match the depthStencil of the
+ render pass. This includes:
+ - formats don't match
+ - formats have matching depth or stencil aspects, but other aspects are missing
+ `
+ )
+ .params(u =>
+ u.combineWithParams([
+ { bundleFormat: 'depth24plus', passFormat: 'depth24plus' }, // control case
+ { bundleFormat: 'depth24plus', passFormat: 'depth16unorm' },
+ { bundleFormat: 'depth24plus', passFormat: 'depth24plus-stencil8' },
+ { bundleFormat: 'stencil8', passFormat: 'depth24plus-stencil8' },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { bundleFormat, passFormat } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase([bundleFormat, passFormat]);
+ })
+ .fn(async t => {
+ const { bundleFormat, passFormat } = t.params;
+ const compatible = bundleFormat === passFormat;
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: [],
+ depthStencilFormat: bundleFormat,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const encoder = t.createEncoder('render pass', {
+ attachmentInfo: {
+ colorFormats: [],
+ depthStencilFormat: passFormat,
+ },
+ });
+ encoder.encoder.executeBundles([bundle]);
+
+ encoder.validateFinish(compatible);
+ });
+
+g.test('depth_stencil_readonly_mismatch')
+ .desc(
+ `
+ Tests executeBundles cannot be called with render bundles that do match the depthStencil
+ readonly state of the render pass.
+ `
+ )
+ .params(u =>
+ u
+ .combine('depthStencilFormat', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('bundleDepthReadOnly', [false, true])
+ .combine('bundleStencilReadOnly', [false, true])
+ .combine('passDepthReadOnly', [false, true])
+ .combine('passStencilReadOnly', [false, true])
+ .filter(p => {
+ // For combined depth/stencil formats the depth and stencil read only state must match
+ // in order to create a valid render bundle or render pass.
+ const depthStencilInfo = kTextureFormatInfo[p.depthStencilFormat];
+ if (depthStencilInfo.depth && depthStencilInfo.stencil) {
+ return (
+ p.passDepthReadOnly === p.passStencilReadOnly &&
+ p.bundleDepthReadOnly === p.bundleStencilReadOnly
+ );
+ }
+ return true;
+ })
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.depthStencilFormat);
+ })
+ .fn(async t => {
+ const {
+ depthStencilFormat,
+ bundleDepthReadOnly,
+ bundleStencilReadOnly,
+ passDepthReadOnly,
+ passStencilReadOnly,
+ } = t.params;
+
+ const compatible =
+ (!passDepthReadOnly || bundleDepthReadOnly === passDepthReadOnly) &&
+ (!passStencilReadOnly || bundleStencilReadOnly === passStencilReadOnly);
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: [],
+ depthStencilFormat,
+ depthReadOnly: bundleDepthReadOnly,
+ stencilReadOnly: bundleStencilReadOnly,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const encoder = t.createEncoder('render pass', {
+ attachmentInfo: {
+ colorFormats: [],
+ depthStencilFormat,
+ depthReadOnly: passDepthReadOnly,
+ stencilReadOnly: passStencilReadOnly,
+ },
+ });
+ encoder.encoder.executeBundles([bundle]);
+
+ encoder.validateFinish(compatible);
+ });
+
+g.test('sample_count_mismatch')
+ .desc(
+ `
+ Tests executeBundles cannot be called with render bundles that do match the sampleCount of the
+ render pass.
+ `
+ )
+ .params(u =>
+ u.combineWithParams([
+ { bundleSamples: 1, passSamples: 1 }, // control case
+ { bundleSamples: 4, passSamples: 4 }, // control case
+ { bundleFormat: 4, passFormat: 1 },
+ { bundleFormat: 1, passFormat: 4 },
+ ])
+ )
+ .fn(async t => {
+ const { bundleSamples, passSamples } = t.params;
+
+ const compatible = bundleSamples === passSamples;
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['bgra8unorm'],
+ sampleCount: bundleSamples,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const encoder = t.createEncoder('render pass', {
+ attachmentInfo: {
+ colorFormats: ['bgra8unorm'],
+ sampleCount: passSamples,
+ },
+ });
+ encoder.encoder.executeBundles([bundle]);
+
+ encoder.validateFinish(compatible);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js
new file mode 100644
index 0000000000..cd8578ca3d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/error_scope.spec.js
@@ -0,0 +1,285 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Error scope validation tests.
+
+Note these must create their own device, not use GPUTest (that one already has error scopes on it).
+
+TODO: (POSTV1) Test error scopes of different threads and make sure they go to the right place.
+TODO: (POSTV1) Test that unhandled errors go the right device, and nowhere if the device was dropped.
+`;
+import { Fixture } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { getGPU } from '../../../common/util/navigator_gpu.js';
+import { assert, raceWithRejectOnTimeout } from '../../../common/util/util.js';
+import { kErrorScopeFilters, kGeneratableErrorScopeFilters } from '../../capability_info.js';
+import { kMaxUnsignedLongLongValue } from '../../constants.js';
+
+class ErrorScopeTests extends Fixture {
+ _device = undefined;
+
+ get device() {
+ assert(this._device !== undefined);
+ return this._device;
+ }
+
+ async init() {
+ await super.init();
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null);
+ const device = await adapter.requestDevice();
+ assert(device !== null);
+ this._device = device;
+ }
+
+ // Generates an error of the given filter type. For now, the errors are generated by calling a
+ // known code-path to cause the error. This can be updated in the future should there be a more
+ // direct way to inject errors.
+ generateError(filter) {
+ switch (filter) {
+ case 'out-of-memory':
+ // Generating an out-of-memory error by allocating a massive buffer.
+ this.device.createBuffer({
+ size: kMaxUnsignedLongLongValue, // Unrealistically massive buffer size
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ break;
+ case 'validation':
+ // Generating a validation error by passing in an invalid usage when creating a buffer.
+ this.device.createBuffer({
+ size: 1024,
+ usage: 0xffff, // Invalid GPUBufferUsage
+ });
+ break;
+ }
+
+ // MAINTENANCE_TODO: This is a workaround for Chromium not flushing. Remove when not needed.
+ this.device.queue.submit([]);
+ }
+
+ // Checks whether the error is of the type expected given the filter.
+ isInstanceOfError(filter, error) {
+ switch (filter) {
+ case 'out-of-memory':
+ return error instanceof GPUOutOfMemoryError;
+ case 'validation':
+ return error instanceof GPUValidationError;
+ case 'internal':
+ return error instanceof GPUInternalError;
+ }
+ }
+
+ // Expect an uncapturederror event to occur. Note: this MUST be awaited, because
+ // otherwise it could erroneously pass by capturing an error from later in the test.
+ async expectUncapturedError(fn) {
+ return this.immediateAsyncExpectation(() => {
+ // MAINTENANCE_TODO: Make arbitrary timeout value a test runner variable
+ const TIMEOUT_IN_MS = 1000;
+
+ const promise = new Promise(resolve => {
+ const eventListener = event => {
+ this.debug(`Got uncaptured error event with ${event.error}`);
+ resolve(event);
+ };
+
+ this.device.addEventListener('uncapturederror', eventListener, { once: true });
+ });
+
+ fn();
+
+ return raceWithRejectOnTimeout(
+ promise,
+ TIMEOUT_IN_MS,
+ 'Timeout occurred waiting for uncaptured error'
+ );
+ });
+ }
+}
+
+export const g = makeTestGroup(ErrorScopeTests);
+
+g.test('simple')
+ .desc(
+ `
+Tests that error scopes catches their expected errors, firing an uncaptured error event otherwise.
+
+- Same error and error filter (popErrorScope should return the error)
+- Different error from filter (uncaptured error should result)
+ `
+ )
+ .params(u =>
+ u.combine('errorType', kGeneratableErrorScopeFilters).combine('errorFilter', kErrorScopeFilters)
+ )
+ .fn(async t => {
+ const { errorType, errorFilter } = t.params;
+ t.device.pushErrorScope(errorFilter);
+
+ if (errorType !== errorFilter) {
+ // Different error case
+ const uncapturedErrorEvent = await t.expectUncapturedError(() => {
+ t.generateError(errorType);
+ });
+ t.expect(t.isInstanceOfError(errorType, uncapturedErrorEvent.error));
+
+ const error = await t.device.popErrorScope();
+ t.expect(error === null);
+ } else {
+ // Same error as filter
+ t.generateError(errorType);
+ const error = await t.device.popErrorScope();
+ t.expect(t.isInstanceOfError(errorType, error));
+ }
+ });
+
+g.test('empty')
+ .desc(
+ `
+Tests that popping an empty error scope stack should reject.
+ `
+ )
+ .fn(async t => {
+ const promise = t.device.popErrorScope();
+ t.shouldReject('OperationError', promise);
+ });
+
+g.test('parent_scope')
+ .desc(
+ `
+Tests that an error bubbles to the correct parent scope.
+
+- Different error types as the parent scope
+- Different depths of non-capturing filters for the generated error
+ `
+ )
+ .params(u =>
+ u
+ .combine('errorFilter', kGeneratableErrorScopeFilters)
+ .combine('stackDepth', [1, 10, 100, 1000])
+ )
+ .fn(async t => {
+ const { errorFilter, stackDepth } = t.params;
+ t.device.pushErrorScope(errorFilter);
+
+ // Push a bunch of error filters onto the stack (none that match errorFilter)
+ const unmatchedFilters = kErrorScopeFilters.filter(filter => {
+ return filter !== errorFilter;
+ });
+ for (let i = 0; i < stackDepth; i++) {
+ t.device.pushErrorScope(unmatchedFilters[i % unmatchedFilters.length]);
+ }
+
+ // Cause the error and then pop all the unrelated filters.
+ t.generateError(errorFilter);
+ const promises = [];
+ for (let i = 0; i < stackDepth; i++) {
+ promises.push(t.device.popErrorScope());
+ }
+ const errors = await Promise.all(promises);
+ t.expect(errors.every(e => e === null));
+
+ // Finally the actual error should have been caught by the parent scope.
+ const error = await t.device.popErrorScope();
+ t.expect(t.isInstanceOfError(errorFilter, error));
+ });
+
+g.test('current_scope')
+ .desc(
+ `
+Tests that an error does not bubbles to parent scopes when local scope matches.
+
+- Different error types as the current scope
+- Different depths of non-capturing filters for the generated error
+ `
+ )
+ .params(u =>
+ u
+ .combine('errorFilter', kGeneratableErrorScopeFilters)
+ .combine('stackDepth', [1, 10, 100, 1000, 100000])
+ )
+ .fn(async t => {
+ const { errorFilter, stackDepth } = t.params;
+
+ // Push a bunch of error filters onto the stack
+ for (let i = 0; i < stackDepth; i++) {
+ t.device.pushErrorScope(kErrorScopeFilters[i % kErrorScopeFilters.length]);
+ }
+
+ // Current scope should catch the error immediately.
+ t.device.pushErrorScope(errorFilter);
+ t.generateError(errorFilter);
+ const error = await t.device.popErrorScope();
+ t.expect(t.isInstanceOfError(errorFilter, error));
+
+ // Remaining scopes shouldn't catch anything.
+ const promises = [];
+ for (let i = 0; i < stackDepth; i++) {
+ promises.push(t.device.popErrorScope());
+ }
+ const errors = await Promise.all(promises);
+ t.expect(errors.every(e => e === null));
+ });
+
+g.test('balanced_siblings')
+ .desc(
+ `
+Tests that sibling error scopes need to be balanced.
+
+- Different error types as the current scope
+- Different number of sibling errors
+ `
+ )
+ .params(u =>
+ u.combine('errorFilter', kErrorScopeFilters).combine('numErrors', [1, 10, 100, 1000])
+ )
+ .fn(async t => {
+ const { errorFilter, numErrors } = t.params;
+
+ const promises = [];
+ for (let i = 0; i < numErrors; i++) {
+ t.device.pushErrorScope(errorFilter);
+ promises.push(t.device.popErrorScope());
+ }
+
+ {
+ // Trying to pop an additional non-exisiting scope should reject.
+ const promise = t.device.popErrorScope();
+ t.shouldReject('OperationError', promise);
+ }
+
+ const errors = await Promise.all(promises);
+ t.expect(errors.every(e => e === null));
+ });
+
+g.test('balanced_nesting')
+ .desc(
+ `
+Tests that nested error scopes need to be balanced.
+
+- Different error types as the current scope
+- Different number of nested errors
+ `
+ )
+ .params(u =>
+ u.combine('errorFilter', kErrorScopeFilters).combine('numErrors', [1, 10, 100, 1000])
+ )
+ .fn(async t => {
+ const { errorFilter, numErrors } = t.params;
+
+ for (let i = 0; i < numErrors; i++) {
+ t.device.pushErrorScope(errorFilter);
+ }
+
+ const promises = [];
+ for (let i = 0; i < numErrors; i++) {
+ promises.push(t.device.popErrorScope());
+ }
+ const errors = await Promise.all(promises);
+ t.expect(errors.every(e => e === null));
+
+ {
+ // Trying to pop an additional non-exisiting scope should reject.
+ const promise = t.device.popErrorScope();
+ t.shouldReject('OperationError', promise);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/getBindGroupLayout.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/getBindGroupLayout.spec.js
new file mode 100644
index 0000000000..e3a6afec4a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/getBindGroupLayout.spec.js
@@ -0,0 +1,202 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+ getBindGroupLayout validation tests.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+
+import { ValidationTest } from './validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('index_range,explicit_layout')
+ .desc(
+ `
+ Test that a validation error is generated if the index exceeds the size of the bind group layouts
+ using a pipeline with an explicit layout.
+ `
+ )
+ .params(u => u.combine('index', [0, 1, 2, 3, 4, 5]))
+ .fn(async t => {
+ const { index } = t.params;
+
+ const pipelineBindGroupLayouts = t.device.createBindGroupLayout({
+ entries: [],
+ });
+
+ const kBindGroupLayoutsSizeInPipelineLayout = 1;
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [pipelineBindGroupLayouts],
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: pipelineLayout,
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+
+ const shouldError = index >= kBindGroupLayoutsSizeInPipelineLayout;
+
+ t.expectValidationError(() => {
+ pipeline.getBindGroupLayout(index);
+ }, shouldError);
+ });
+
+g.test('index_range,auto_layout')
+ .desc(
+ `
+ Test that a validation error is generated if the index exceeds the size of the bind group layouts
+ using a pipeline with an auto layout.
+ `
+ )
+ .params(u => u.combine('index', [0, 1, 2, 3, 4, 5]))
+ .fn(async t => {
+ const { index } = t.params;
+
+ const kBindGroupLayoutsSizeInPipelineLayout = 1;
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var<uniform> binding: f32;
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ _ = binding;
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+
+ const shouldError = index >= kBindGroupLayoutsSizeInPipelineLayout;
+
+ t.expectValidationError(() => {
+ pipeline.getBindGroupLayout(index);
+ }, shouldError);
+ });
+
+g.test('unique_js_object,auto_layout')
+ .desc(
+ `
+ Test that getBindGroupLayout returns a new JavaScript object for each call.
+ `
+ )
+ .fn(async t => {
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var<uniform> binding: f32;
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ _ = binding;
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+
+ const kIndex = 0;
+ const bgl1 = pipeline.getBindGroupLayout(kIndex);
+ bgl1.extra = 42;
+ const bgl2 = pipeline.getBindGroupLayout(kIndex);
+
+ assert(bgl1 !== bgl2, 'objects are not the same object');
+ assert(bgl2.extra === undefined, 'objects do not retain expando properties');
+ });
+
+g.test('unique_js_object,explicit_layout')
+ .desc(
+ `
+ Test that getBindGroupLayout returns a new JavaScript object for each call.
+ `
+ )
+ .fn(async t => {
+ const pipelineBindGroupLayouts = t.device.createBindGroupLayout({
+ entries: [],
+ });
+
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [pipelineBindGroupLayouts],
+ });
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: pipelineLayout,
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+
+ const kIndex = 0;
+ const bgl1 = pipeline.getBindGroupLayout(kIndex);
+ bgl1.extra = 42;
+ const bgl2 = pipeline.getBindGroupLayout(kIndex);
+
+ assert(bgl1 !== bgl2, 'objects are not the same object');
+ assert(bgl2.extra === undefined, 'objects do not retain expando properties');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_related.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_related.spec.js
new file mode 100644
index 0000000000..399e454113
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_related.spec.js
@@ -0,0 +1,230 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for buffer related parameters for buffer <-> texture copies`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kSizedTextureFormats,
+ kTextureDimensions,
+ kTextureFormatInfo,
+ textureDimensionAndFormatCompatible,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { kResourceStates } from '../../../gpu_test.js';
+import { kImageCopyTypes } from '../../../util/texture/layout.js';
+
+import { ImageCopyTest, formatCopyableWithMethod } from './image_copy.js';
+
+export const g = makeTestGroup(ImageCopyTest);
+
+g.test('buffer_state')
+ .desc(
+ `
+Test that the buffer must be valid and not destroyed.
+- for all buffer <-> texture copy methods
+- for various buffer states
+`
+ )
+ .params(u =>
+ u //
+ // B2B copy validations are at api,validation,encoding,cmds,copyBufferToBuffer.spec.ts
+ .combine('method', ['CopyB2T', 'CopyT2B'])
+ .combine('state', kResourceStates)
+ )
+ .fn(async t => {
+ const { method, state } = t.params;
+
+ // A valid buffer.
+ const buffer = t.createBufferWithState(state, {
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ // Invalid buffer will fail finish, and destroyed buffer will fail submit
+ const submit = state !== 'invalid';
+ const success = state === 'valid';
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit }
+ );
+ });
+
+g.test('buffer,device_mismatch')
+ .desc('Tests the image copies cannot be called with a buffer created from another device')
+ .paramsSubcasesOnly(u =>
+ u.combine('method', ['CopyB2T', 'CopyT2B']).combine('mismatched', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { method, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const buffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const success = !mismatched;
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit: success }
+ );
+ });
+
+g.test('usage')
+ .desc(
+ `
+Test the buffer must have the appropriate COPY_SRC/COPY_DST usage.
+TODO update such that it tests
+- for all buffer source usages
+- for all buffer destination usages
+`
+ )
+ .params(u =>
+ u
+ // B2B copy validations are at api,validation,encoding,cmds,copyBufferToBuffer.spec.ts
+ .combine('method', ['CopyB2T', 'CopyT2B'])
+ .beginSubcases()
+ .combine('usage', [
+ GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.UNIFORM,
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.UNIFORM,
+ GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.COPY_DST,
+ ])
+ )
+ .fn(async t => {
+ const { method, usage } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ const success =
+ method === 'CopyB2T'
+ ? (usage & GPUBufferUsage.COPY_SRC) !== 0
+ : (usage & GPUBufferUsage.COPY_DST) !== 0;
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit: success }
+ );
+ });
+
+g.test('bytes_per_row_alignment')
+ .desc(
+ `
+Test that bytesPerRow must be a multiple of 256 for CopyB2T and CopyT2B if it is required.
+- for all copy methods between linear data and textures
+- for all texture dimensions
+- for all sized formats.
+- for various bytesPerRow aligned to 256 or not
+- for various number of blocks rows copied
+`
+ )
+ .params(u =>
+ u //
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('bytesPerRow', [undefined, 0, 1, 255, 256, 257, 512])
+ .combine('copyHeightInBlocks', [0, 1, 2, 3])
+ .expand('_textureHeightInBlocks', p => [
+ p.copyHeightInBlocks === 0 ? 1 : p.copyHeightInBlocks,
+ ])
+ .unless(p => p.dimension === '1d' && p.copyHeightInBlocks > 1)
+ // Depth/stencil format copies must copy the whole subresource.
+ .unless(p => {
+ const info = kTextureFormatInfo[p.format];
+ return (info.depth || info.stencil) && p.copyHeightInBlocks !== p._textureHeightInBlocks;
+ })
+ // bytesPerRow must be specified and it must be equal or greater than the bytes size of each row if we are copying multiple rows.
+ // Note that we are copying one single block on each row in this test.
+ .filter(
+ ({ format, bytesPerRow, copyHeightInBlocks }) =>
+ (bytesPerRow === undefined && copyHeightInBlocks <= 1) ||
+ (bytesPerRow !== undefined && bytesPerRow >= kTextureFormatInfo[format].bytesPerBlock)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ method,
+ dimension,
+ format,
+ bytesPerRow,
+ copyHeightInBlocks,
+ _textureHeightInBlocks,
+ } = t.params;
+
+ const info = kTextureFormatInfo[format];
+
+ const buffer = t.device.createBuffer({
+ size: 512 * 8 * 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ let success = false;
+ // writeTexture doesn't require bytesPerRow to be 256-byte aligned.
+ if (method === 'WriteTexture') success = true;
+ // If the copy height <= 1, bytesPerRow is not required.
+ if (copyHeightInBlocks <= 1 && bytesPerRow === undefined) success = true;
+ // If bytesPerRow > 0 and it is a multiple of 256, it will succeed if other parameters are valid.
+ if (bytesPerRow !== undefined && bytesPerRow > 0 && bytesPerRow % 256 === 0) success = true;
+
+ const size = [info.blockWidth, _textureHeightInBlocks * info.blockHeight, 1];
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const copySize = [info.blockWidth, copyHeightInBlocks * info.blockHeight, 1];
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(buffer, texture, { bytesPerRow }, copySize, {
+ dataSize: 512 * 8 * 16,
+ method,
+ success,
+ submit: success,
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_texture_copies.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_texture_copies.spec.js
new file mode 100644
index 0000000000..c9a2bbfb40
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/buffer_texture_copies.spec.js
@@ -0,0 +1,441 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyTextureToBuffer and copyBufferToTexture validation tests not covered by
+the general image_copy tests, or by destroyed,*.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../common/util/util.js';
+import {
+ kDepthStencilFormats,
+ kBufferUsages,
+ kTextureUsages,
+ depthStencilBufferTextureCopySupported,
+ depthStencilFormatAspectSize,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { align } from '../../../util/math.js';
+import { kBufferCopyAlignment, kBytesPerRowAlignment } from '../../../util/texture/layout.js';
+import { ValidationTest } from '../validation_test.js';
+
+class ImageCopyTest extends ValidationTest {
+ testCopyBufferToTexture(source, destination, copySize, isSuccess) {
+ const { encoder, validateFinishAndSubmit } = this.createEncoder('non-pass');
+ encoder.copyBufferToTexture(source, destination, copySize);
+ validateFinishAndSubmit(isSuccess, true);
+ }
+
+ testCopyTextureToBuffer(source, destination, copySize, isSuccess) {
+ const { encoder, validateFinishAndSubmit } = this.createEncoder('non-pass');
+ encoder.copyTextureToBuffer(source, destination, copySize);
+ validateFinishAndSubmit(isSuccess, true);
+ }
+
+ testWriteTexture(destination, uploadData, dataLayout, copySize, isSuccess) {
+ this.expectGPUError(
+ 'validation',
+ () => this.queue.writeTexture(destination, uploadData, dataLayout, copySize),
+ !isSuccess
+ );
+ }
+}
+
+export const g = makeTestGroup(ImageCopyTest);
+
+g.test('depth_stencil_format,copy_usage_and_aspect')
+ .desc(
+ `
+ Validate the combination of usage and aspect of each depth stencil format in copyBufferToTexture,
+ copyTextureToBuffer and writeTexture. See https://gpuweb.github.io/gpuweb/#depth-formats for more
+ details.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('aspect', ['all', 'depth-only', 'stencil-only'])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const { format, aspect } = t.params;
+
+ const textureSize = { width: 1, height: 1, depthOrArrayLayers: 1 };
+ const texture = t.device.createTexture({
+ size: textureSize,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const uploadBufferSize = 32;
+ const buffer = t.device.createBuffer({
+ size: uploadBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ {
+ const success = depthStencilBufferTextureCopySupported('CopyB2T', format, aspect);
+ t.testCopyBufferToTexture({ buffer }, { texture, aspect }, textureSize, success);
+ }
+
+ {
+ const success = depthStencilBufferTextureCopySupported('CopyT2B', format, aspect);
+ t.testCopyTextureToBuffer({ texture, aspect }, { buffer }, textureSize, success);
+ }
+
+ {
+ const success = depthStencilBufferTextureCopySupported('WriteTexture', format, aspect);
+ const uploadData = new Uint8Array(uploadBufferSize);
+ t.testWriteTexture({ texture, aspect }, uploadData, {}, textureSize, success);
+ }
+ });
+
+g.test('depth_stencil_format,copy_buffer_size')
+ .desc(
+ `
+ Validate the minimum buffer size for each depth stencil format in copyBufferToTexture,
+ copyTextureToBuffer and writeTexture.
+
+ Given a depth stencil format, a copy aspect ('depth-only' or 'stencil-only'), the copy method
+ (buffer-to-texture or texture-to-buffer) and the copy size, validate
+ - if the copy can be successfully executed with the minimum required buffer size.
+ - if the copy fails with a validation error when the buffer size is less than the minimum
+ required buffer size.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .combine('aspect', ['depth-only', 'stencil-only'])
+ .combine('copyType', ['CopyB2T', 'CopyT2B', 'WriteTexture'])
+ .filter(param =>
+ depthStencilBufferTextureCopySupported(param.copyType, param.format, param.aspect)
+ )
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 8, height: 1, depthOrArrayLayers: 1 },
+ { width: 4, height: 4, depthOrArrayLayers: 1 },
+ { width: 4, height: 4, depthOrArrayLayers: 3 },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const { format, aspect, copyType, copySize } = t.params;
+
+ const texture = t.device.createTexture({
+ size: copySize,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const texelAspectSize = depthStencilFormatAspectSize(format, aspect);
+ assert(texelAspectSize > 0);
+
+ const bytesPerRowAlignment = copyType === 'WriteTexture' ? 1 : kBytesPerRowAlignment;
+ const bytesPerRow = align(texelAspectSize * copySize.width, bytesPerRowAlignment);
+ const rowsPerImage = copySize.height;
+ const minimumBufferSize =
+ bytesPerRow * (rowsPerImage * copySize.depthOrArrayLayers - 1) +
+ align(texelAspectSize * copySize.width, kBufferCopyAlignment);
+ assert(minimumBufferSize > kBufferCopyAlignment);
+
+ const bigEnoughBuffer = t.device.createBuffer({
+ size: minimumBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ const smallerBuffer = t.device.createBuffer({
+ size: minimumBufferSize - kBufferCopyAlignment,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ if (copyType === 'CopyB2T') {
+ t.testCopyBufferToTexture(
+ { buffer: bigEnoughBuffer, bytesPerRow, rowsPerImage },
+ { texture, aspect },
+ copySize,
+ true
+ );
+
+ t.testCopyBufferToTexture(
+ { buffer: smallerBuffer, bytesPerRow, rowsPerImage },
+ { texture, aspect },
+ copySize,
+ false
+ );
+ } else if (copyType === 'CopyT2B') {
+ t.testCopyTextureToBuffer(
+ { texture, aspect },
+ { buffer: bigEnoughBuffer, bytesPerRow, rowsPerImage },
+ copySize,
+ true
+ );
+
+ t.testCopyTextureToBuffer(
+ { texture, aspect },
+ { buffer: smallerBuffer, bytesPerRow, rowsPerImage },
+ copySize,
+ false
+ );
+ } else if (copyType === 'WriteTexture') {
+ const enoughUploadData = new Uint8Array(minimumBufferSize);
+ const smallerUploadData = new Uint8Array(minimumBufferSize - kBufferCopyAlignment);
+ t.testWriteTexture(
+ { texture, aspect },
+ enoughUploadData,
+ {
+ bytesPerRow,
+ rowsPerImage,
+ },
+ copySize,
+ true
+ );
+
+ t.testWriteTexture(
+ { texture, aspect },
+ smallerUploadData,
+ {
+ bytesPerRow,
+ rowsPerImage,
+ },
+ copySize,
+ false
+ );
+ } else {
+ unreachable();
+ }
+ });
+
+g.test('depth_stencil_format,copy_buffer_offset')
+ .desc(
+ `
+ Validate for every depth stencil formats the buffer offset must be a multiple of 4 in
+ copyBufferToTexture() and copyTextureToBuffer(), but the offset in writeTexture() doesn't always
+ need to be a multiple of 4.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kDepthStencilFormats)
+ .combine('aspect', ['depth-only', 'stencil-only'])
+ .combine('copyType', ['CopyB2T', 'CopyT2B', 'WriteTexture'])
+ .filter(param =>
+ depthStencilBufferTextureCopySupported(param.copyType, param.format, param.aspect)
+ )
+ .beginSubcases()
+ .combine('offset', [1, 2, 4, 6, 8])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceForTextureFormatOrSkipTestCase(format);
+ })
+ .fn(async t => {
+ const { format, aspect, copyType, offset } = t.params;
+
+ const textureSize = { width: 4, height: 4, depthOrArrayLayers: 1 };
+
+ const texture = t.device.createTexture({
+ size: textureSize,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const texelAspectSize = depthStencilFormatAspectSize(format, aspect);
+ assert(texelAspectSize > 0);
+
+ const bytesPerRowAlignment = copyType === 'WriteTexture' ? 1 : kBytesPerRowAlignment;
+ const bytesPerRow = align(texelAspectSize * textureSize.width, bytesPerRowAlignment);
+ const rowsPerImage = textureSize.height;
+ const minimumBufferSize =
+ bytesPerRow * (rowsPerImage * textureSize.depthOrArrayLayers - 1) +
+ align(texelAspectSize * textureSize.width, kBufferCopyAlignment);
+ assert(minimumBufferSize > kBufferCopyAlignment);
+
+ const buffer = t.device.createBuffer({
+ size: align(minimumBufferSize + offset, kBufferCopyAlignment),
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const isSuccess = copyType === 'WriteTexture' ? true : offset % 4 === 0;
+
+ if (copyType === 'CopyB2T') {
+ t.testCopyBufferToTexture(
+ { buffer, offset, bytesPerRow, rowsPerImage },
+ { texture, aspect },
+ textureSize,
+ isSuccess
+ );
+ } else if (copyType === 'CopyT2B') {
+ t.testCopyTextureToBuffer(
+ { texture, aspect },
+ { buffer, offset, bytesPerRow, rowsPerImage },
+ textureSize,
+ isSuccess
+ );
+ } else if (copyType === 'WriteTexture') {
+ const uploadData = new Uint8Array(minimumBufferSize + offset);
+ t.testWriteTexture(
+ { texture, aspect },
+ uploadData,
+ {
+ offset,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ textureSize,
+ isSuccess
+ );
+ } else {
+ unreachable();
+ }
+ });
+
+g.test('sample_count')
+ .desc(
+ `
+ Test that the texture sample count. Check that a validation error is generated if sample count is
+ not 1.
+ `
+ )
+ .params(u =>
+ u //
+ // writeTexture is handled by writeTexture.spec.ts.
+ .combine('copyType', ['CopyB2T', 'CopyT2B'])
+ .beginSubcases()
+ .combine('sampleCount', [1, 4])
+ )
+ .fn(async t => {
+ const { sampleCount, copyType } = t.params;
+
+ let usage = GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST;
+ // WebGPU SPEC requires multisampled textures must have RENDER_ATTACHMENT usage.
+ if (sampleCount > 1) {
+ usage |= GPUTextureUsage.RENDER_ATTACHMENT;
+ }
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16 },
+ sampleCount,
+ format: 'bgra8unorm',
+ usage,
+ });
+
+ const uploadBufferSize = 32;
+ const buffer = t.device.createBuffer({
+ size: uploadBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const textureSize = { width: 1, height: 1, depthOrArrayLayers: 1 };
+
+ const isSuccess = sampleCount === 1;
+
+ if (copyType === 'CopyB2T') {
+ t.testCopyBufferToTexture({ buffer }, { texture }, textureSize, isSuccess);
+ } else if (copyType === 'CopyT2B') {
+ t.testCopyTextureToBuffer({ texture }, { buffer }, textureSize, isSuccess);
+ }
+ });
+
+const kRequiredTextureUsage = {
+ CopyT2B: GPUConst.TextureUsage.COPY_SRC,
+ CopyB2T: GPUConst.TextureUsage.COPY_DST,
+};
+const kRequiredBufferUsage = {
+ CopyB2T: GPUConst.BufferUsage.COPY_SRC,
+ CopyT2B: GPUConst.BufferUsage.COPY_DST,
+};
+
+g.test('texture_buffer_usages')
+ .desc(
+ `
+ Tests calling copyTextureToBuffer or copyBufferToTexture with the texture and the buffer missed
+ COPY_SRC, COPY_DST usage respectively.
+ - texture and buffer {with, without} COPY_SRC and COPY_DST usage.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('copyType', ['CopyB2T', 'CopyT2B'])
+ .beginSubcases()
+ .combine('textureUsage', kTextureUsages)
+ .expand('_textureUsageValid', p => [p.textureUsage === kRequiredTextureUsage[p.copyType]])
+ .combine('bufferUsage', kBufferUsages)
+ .expand('_bufferUsageValid', p => [p.bufferUsage === kRequiredBufferUsage[p.copyType]])
+ .filter(p => p._textureUsageValid || p._bufferUsageValid)
+ )
+ .fn(async t => {
+ const { copyType, textureUsage, _textureUsageValid, bufferUsage, _bufferUsageValid } = t.params;
+
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16 },
+ format: 'rgba8unorm',
+ usage: textureUsage,
+ });
+
+ const uploadBufferSize = 32;
+ const buffer = t.device.createBuffer({
+ size: uploadBufferSize,
+ usage: bufferUsage,
+ });
+
+ const textureSize = { width: 1, height: 1, depthOrArrayLayers: 1 };
+
+ const isSuccess = _textureUsageValid && _bufferUsageValid;
+ if (copyType === 'CopyB2T') {
+ t.testCopyBufferToTexture({ buffer }, { texture }, textureSize, isSuccess);
+ } else if (copyType === 'CopyT2B') {
+ t.testCopyTextureToBuffer({ texture }, { buffer }, textureSize, isSuccess);
+ }
+ });
+
+g.test('device_mismatch')
+ .desc(
+ `
+ Tests copyBufferToTexture and copyTextureToBuffer cannot be called with a buffer or a texture
+ created from another device.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('copyType', ['CopyB2T', 'CopyT2B'])
+ .beginSubcases()
+ .combineWithParams([
+ { bufMismatched: false, texMismatched: false }, // control case
+ { bufMismatched: true, texMismatched: false },
+ { bufMismatched: false, texMismatched: true },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { copyType, bufMismatched, texMismatched } = t.params;
+
+ const uploadBufferSize = 32;
+ const buffer = (bufMismatched ? t.mismatchedDevice : t.device).createBuffer({
+ size: uploadBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ const textureSize = { width: 1, height: 1, depthOrArrayLayers: 1 };
+ const texture = (texMismatched ? t.mismatchedDevice : t.device).createTexture({
+ size: textureSize,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+ t.trackForCleanup(texture);
+
+ const isValid = !bufMismatched && !texMismatched;
+
+ if (copyType === 'CopyB2T') {
+ t.testCopyBufferToTexture({ buffer }, { texture }, textureSize, isValid);
+ } else if (copyType === 'CopyT2B') {
+ t.testCopyTextureToBuffer({ texture }, { buffer }, textureSize, isValid);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js
new file mode 100644
index 0000000000..b51389dbe8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/image_copy.js
@@ -0,0 +1,216 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import {
+ kTextureFormatInfo,
+ depthStencilFormatCopyableAspects,
+} from '../../../capability_info.js';
+import { align } from '../../../util/math.js';
+
+import { ValidationTest } from '../validation_test.js';
+
+export class ImageCopyTest extends ValidationTest {
+ testRun(textureCopyView, textureDataLayout, size, { method, dataSize, success, submit = false }) {
+ switch (method) {
+ case 'WriteTexture': {
+ const data = new Uint8Array(dataSize);
+
+ this.expectValidationError(() => {
+ this.device.queue.writeTexture(textureCopyView, data, textureDataLayout, size);
+ }, !success);
+
+ break;
+ }
+ case 'CopyB2T': {
+ const buffer = this.device.createBuffer({
+ size: dataSize,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ this.trackForCleanup(buffer);
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyBufferToTexture({ buffer, ...textureDataLayout }, textureCopyView, size);
+
+ if (submit) {
+ const cmd = encoder.finish();
+ this.expectValidationError(() => {
+ this.device.queue.submit([cmd]);
+ }, !success);
+ } else {
+ this.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ }
+
+ break;
+ }
+ case 'CopyT2B': {
+ const buffer = this.device.createBuffer({
+ size: dataSize,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(buffer);
+
+ const encoder = this.device.createCommandEncoder();
+ encoder.copyTextureToBuffer(textureCopyView, { buffer, ...textureDataLayout }, size);
+
+ if (submit) {
+ const cmd = encoder.finish();
+ this.expectValidationError(() => {
+ this.device.queue.submit([cmd]);
+ }, !success);
+ } else {
+ this.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ }
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Creates a texture when all that is needed is an aligned texture given the format and desired
+ * dimensions/origin. The resultant texture guarantees that a copy with the same size and origin
+ * should be possible.
+ */
+ createAlignedTexture(
+ format,
+ size = {
+ width: 1,
+ height: 1,
+ depthOrArrayLayers: 1,
+ },
+ origin = { x: 0, y: 0, z: 0 },
+ dimension = '2d'
+ ) {
+ const info = kTextureFormatInfo[format];
+ const alignedSize = {
+ width: align(Math.max(1, size.width + origin.x), info.blockWidth),
+ height: align(Math.max(1, size.height + origin.y), info.blockHeight),
+ depthOrArrayLayers: Math.max(1, size.depthOrArrayLayers + origin.z),
+ };
+ return this.device.createTexture({
+ size: alignedSize,
+ dimension,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+ }
+
+ testBuffer(
+ buffer,
+ texture,
+ textureDataLayout,
+ size,
+ { method, dataSize, success, submit = true }
+ ) {
+ switch (method) {
+ case 'WriteTexture': {
+ const data = new Uint8Array(dataSize);
+
+ this.expectValidationError(() => {
+ this.device.queue.writeTexture({ texture }, data, textureDataLayout, size);
+ }, !success);
+
+ break;
+ }
+ case 'CopyB2T': {
+ const { encoder, validateFinish, validateFinishAndSubmit } = this.createEncoder('non-pass');
+ encoder.copyBufferToTexture({ buffer, ...textureDataLayout }, { texture }, size);
+
+ if (submit) {
+ // validation error is expected to come from the submit and encoding should succeed
+ validateFinishAndSubmit(true, success);
+ } else {
+ // validation error is expected to come from the encoding
+ validateFinish(success);
+ }
+
+ break;
+ }
+ case 'CopyT2B': {
+ const { encoder, validateFinish, validateFinishAndSubmit } = this.createEncoder('non-pass');
+ encoder.copyTextureToBuffer({ texture }, { buffer, ...textureDataLayout }, size);
+
+ if (submit) {
+ // validation error is expected to come from the submit and encoding should succeed
+ validateFinishAndSubmit(true, success);
+ } else {
+ // validation error is expected to come from the encoding
+ validateFinish(success);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+// For testing divisibility by a number we test all the values returned by this function:
+function valuesToTestDivisibilityBy(number) {
+ const values = [];
+ for (let i = 0; i <= 2 * number; ++i) {
+ values.push(i);
+ }
+ values.push(3 * number);
+ return values;
+}
+
+// This is a helper function used for expanding test parameters for offset alignment, by spec
+export function texelBlockAlignmentTestExpanderForOffset({ format }) {
+ const info = kTextureFormatInfo[format];
+ if (info.depth || info.stencil) {
+ return valuesToTestDivisibilityBy(4);
+ }
+
+ return valuesToTestDivisibilityBy(kTextureFormatInfo[format].bytesPerBlock);
+}
+
+// This is a helper function used for expanding test parameters for texel block alignment tests on rowsPerImage
+export function texelBlockAlignmentTestExpanderForRowsPerImage({ format }) {
+ return valuesToTestDivisibilityBy(kTextureFormatInfo[format].blockHeight);
+}
+
+// This is a helper function used for expanding test parameters for texel block alignment tests on origin and size
+export function texelBlockAlignmentTestExpanderForValueToCoordinate({ format, coordinateToTest }) {
+ switch (coordinateToTest) {
+ case 'x':
+ case 'width':
+ return valuesToTestDivisibilityBy(kTextureFormatInfo[format].blockWidth);
+
+ case 'y':
+ case 'height':
+ return valuesToTestDivisibilityBy(kTextureFormatInfo[format].blockHeight);
+
+ case 'z':
+ case 'depthOrArrayLayers':
+ return valuesToTestDivisibilityBy(1);
+ }
+}
+
+// This is a helper function used for filtering test parameters
+export function formatCopyableWithMethod({ format, method }) {
+ const info = kTextureFormatInfo[format];
+ if (info.depth || info.stencil) {
+ const supportedAspects = depthStencilFormatCopyableAspects(method, format);
+
+ return supportedAspects.length > 0;
+ }
+ if (method === 'CopyT2B') {
+ return info.copySrc;
+ } else {
+ return info.copyDst;
+ }
+}
+
+// This is a helper function used for filtering test parameters
+export function getACopyableAspectWithMethod({ format, method }) {
+ const info = kTextureFormatInfo[format];
+ if (info.depth || info.stencil) {
+ const supportedAspects = depthStencilFormatCopyableAspects(method, format);
+
+ return supportedAspects[0];
+ }
+ return 'all';
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/layout_related.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/layout_related.spec.js
new file mode 100644
index 0000000000..3fbf2bd6cd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/layout_related.spec.js
@@ -0,0 +1,480 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for the linear data layout of linear data <-> texture copies
+
+TODO check if the tests need to be updated to support aspects of depth-stencil textures`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kSizedTextureFormats,
+ textureDimensionAndFormatCompatible,
+ kTextureDimensions,
+} from '../../../capability_info.js';
+import { align } from '../../../util/math.js';
+import {
+ bytesInACompleteRow,
+ dataBytesForCopyOrOverestimate,
+ dataBytesForCopyOrFail,
+ kImageCopyTypes,
+} from '../../../util/texture/layout.js';
+
+import {
+ ImageCopyTest,
+ texelBlockAlignmentTestExpanderForOffset,
+ texelBlockAlignmentTestExpanderForRowsPerImage,
+ formatCopyableWithMethod,
+} from './image_copy.js';
+
+export const g = makeTestGroup(ImageCopyTest);
+
+g.test('bound_on_rows_per_image')
+ .desc(
+ `
+Test that rowsPerImage must be at least the copy height (if defined).
+- for various copy methods
+- for all texture dimensions
+- for various values of rowsPerImage including undefined
+- for various copy heights
+- for various copy depths
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combineWithParams([
+ { dimension: '1d', size: [4, 1, 1] },
+ { dimension: '2d', size: [4, 4, 1] },
+ { dimension: '2d', size: [4, 4, 3] },
+ { dimension: '3d', size: [4, 4, 3] },
+ ])
+ .beginSubcases()
+ .combine('rowsPerImage', [undefined, 0, 1, 2, 1024])
+ .combine('copyHeightInBlocks', [0, 1, 2])
+ .combine('copyDepth', [1, 3])
+ .unless(p => p.dimension === '1d' && p.copyHeightInBlocks !== 1)
+ .unless(p => p.copyDepth > p.size[2])
+ )
+ .fn(async t => {
+ const { rowsPerImage, copyHeightInBlocks, copyDepth, dimension, size, method } = t.params;
+
+ const format = 'rgba8unorm';
+ const copyHeight = copyHeightInBlocks * kTextureFormatInfo[format].blockHeight;
+
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const layout = { bytesPerRow: 1024, rowsPerImage };
+ const copySize = { width: 0, height: copyHeight, depthOrArrayLayers: copyDepth };
+ const { minDataSizeOrOverestimate, copyValid } = dataBytesForCopyOrOverestimate({
+ layout,
+ format,
+ copySize,
+ method,
+ });
+
+ t.testRun({ texture }, layout, copySize, {
+ dataSize: minDataSizeOrOverestimate,
+ method,
+ success: copyValid,
+ });
+ });
+
+g.test('copy_end_overflows_u64')
+ .desc(
+ `
+Test an error is produced when offset+requiredBytesInCopy overflows GPUSize64.
+- for various copy methods
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .beginSubcases()
+ .combineWithParams([
+ { bytesPerRow: 2 ** 31, rowsPerImage: 2 ** 31, depthOrArrayLayers: 1, _success: true }, // success case
+ { bytesPerRow: 2 ** 31, rowsPerImage: 2 ** 31, depthOrArrayLayers: 16, _success: false }, // bytesPerRow * rowsPerImage * (depthOrArrayLayers - 1) overflows.
+ ])
+ )
+ .fn(async t => {
+ const { method, bytesPerRow, rowsPerImage, depthOrArrayLayers, _success } = t.params;
+
+ const texture = t.device.createTexture({
+ size: [1, 1, depthOrArrayLayers],
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ t.testRun(
+ { texture },
+ { bytesPerRow, rowsPerImage },
+ { width: 1, height: 1, depthOrArrayLayers },
+ {
+ dataSize: 10000,
+ method,
+ success: _success,
+ }
+ );
+ });
+
+g.test('required_bytes_in_copy')
+ .desc(
+ `
+Test the computation of requiredBytesInCopy by computing the minimum data size for the copy and checking success/error at the boundary.
+- for various copy methods
+- for all formats
+- for all dimensions
+- for various extra bytesPerRow/rowsPerImage
+- for various copy sizes
+- for various offsets in the linear data
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combineWithParams([
+ { bytesPerRowPadding: 0, rowsPerImagePaddingInBlocks: 0 }, // no padding
+ { bytesPerRowPadding: 0, rowsPerImagePaddingInBlocks: 6 }, // rowsPerImage padding
+ { bytesPerRowPadding: 6, rowsPerImagePaddingInBlocks: 0 }, // bytesPerRow padding
+ { bytesPerRowPadding: 15, rowsPerImagePaddingInBlocks: 17 }, // both paddings
+ ])
+ .combineWithParams([
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 5, _offsetMultiplier: 0 }, // standard copy
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 3, _offsetMultiplier: 11 }, // standard copy, offset > 0
+ { copyWidthInBlocks: 256, copyHeightInBlocks: 3, copyDepth: 2, _offsetMultiplier: 0 }, // copyWidth is 256-aligned
+ { copyWidthInBlocks: 0, copyHeightInBlocks: 4, copyDepth: 5, _offsetMultiplier: 0 }, // empty copy because of width
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 0, copyDepth: 5, _offsetMultiplier: 0 }, // empty copy because of height
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 0, _offsetMultiplier: 13 }, // empty copy because of depth, offset > 0
+ { copyWidthInBlocks: 1, copyHeightInBlocks: 4, copyDepth: 5, _offsetMultiplier: 0 }, // copyWidth = 1
+ { copyWidthInBlocks: 3, copyHeightInBlocks: 1, copyDepth: 5, _offsetMultiplier: 15 }, // copyHeight = 1, offset > 0
+ { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 1, _offsetMultiplier: 0 }, // copyDepth = 1
+ { copyWidthInBlocks: 7, copyHeightInBlocks: 1, copyDepth: 1, _offsetMultiplier: 0 }, // copyHeight = 1 and copyDepth = 1
+ ])
+ // The test texture size will be rounded up from the copy size to the next valid texture size.
+ // If the format is a depth/stencil format, its copy size must equal to subresource's size.
+ // So filter out depth/stencil cases where the rounded-up texture size would be different from the copy size.
+ .filter(({ format, copyWidthInBlocks, copyHeightInBlocks, copyDepth }) => {
+ const info = kTextureFormatInfo[format];
+ return (
+ (!info.depth && !info.stencil) ||
+ (copyWidthInBlocks > 0 && copyHeightInBlocks > 0 && copyDepth > 0)
+ );
+ })
+ .unless(p => p.dimension === '1d' && (p.copyHeightInBlocks > 1 || p.copyDepth > 1))
+ .expand('offset', p => {
+ const info = kTextureFormatInfo[p.format];
+ if (info.depth || info.stencil) {
+ return [p._offsetMultiplier * 4];
+ }
+ return [p._offsetMultiplier * info.bytesPerBlock];
+ })
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ offset,
+ bytesPerRowPadding,
+ rowsPerImagePaddingInBlocks,
+ copyWidthInBlocks,
+ copyHeightInBlocks,
+ copyDepth,
+ format,
+ dimension,
+ method,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ // In the CopyB2T and CopyT2B cases we need to have bytesPerRow 256-aligned,
+ // to make this happen we align the bytesInACompleteRow value and multiply
+ // bytesPerRowPadding by 256.
+ const bytesPerRowAlignment = method === 'WriteTexture' ? 1 : 256;
+ const copyWidth = copyWidthInBlocks * info.blockWidth;
+ const copyHeight = copyHeightInBlocks * info.blockHeight;
+ const rowsPerImage = copyHeight + rowsPerImagePaddingInBlocks * info.blockHeight;
+ const bytesPerRow =
+ align(bytesInACompleteRow(copyWidth, format), bytesPerRowAlignment) +
+ bytesPerRowPadding * bytesPerRowAlignment;
+ const copySize = { width: copyWidth, height: copyHeight, depthOrArrayLayers: copyDepth };
+
+ const layout = { offset, bytesPerRow, rowsPerImage };
+ const minDataSize = dataBytesForCopyOrFail({ layout, format, copySize, method });
+
+ const texture = t.createAlignedTexture(format, copySize, undefined, dimension);
+
+ t.testRun({ texture }, layout, copySize, {
+ dataSize: minDataSize,
+ method,
+ success: true,
+ });
+
+ if (minDataSize > 0) {
+ t.testRun({ texture }, layout, copySize, {
+ dataSize: minDataSize - 1,
+ method,
+ success: false,
+ });
+ }
+ });
+
+g.test('rows_per_image_alignment')
+ .desc(
+ `
+Test that rowsPerImage has no alignment constraints.
+- for various copy methods
+- for all sized format
+- for all dimensions
+- for various rowsPerImage
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .expand('rowsPerImage', texelBlockAlignmentTestExpanderForRowsPerImage)
+ // Copy height is info.blockHeight, so rowsPerImage must be equal or greater than it.
+ .filter(({ rowsPerImage, format }) => rowsPerImage >= kTextureFormatInfo[format].blockHeight)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { rowsPerImage, format, method } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const size = { width: info.blockWidth, height: info.blockHeight, depthOrArrayLayers: 1 };
+ const texture = t.device.createTexture({
+ size,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ t.testRun({ texture }, { bytesPerRow: 256, rowsPerImage }, size, {
+ dataSize: info.bytesPerBlock,
+ method,
+ success: true,
+ });
+ });
+
+g.test('offset_alignment')
+ .desc(
+ `
+Test the alignment requirement on the linear data offset (block size, or 4 for depth-stencil).
+- for various copy methods
+- for all sized formats
+- for all dimensions
+- for various linear data offsets
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .expand('offset', texelBlockAlignmentTestExpanderForOffset)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { format, offset, method } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const size = { width: info.blockWidth, height: info.blockHeight, depthOrArrayLayers: 1 };
+ const texture = t.device.createTexture({
+ size,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ let success = false;
+ if (method === 'WriteTexture') success = true;
+ if (info.depth || info.stencil) {
+ if (offset % 4 === 0) success = true;
+ } else {
+ if (offset % info.bytesPerBlock === 0) success = true;
+ }
+
+ t.testRun({ texture }, { offset, bytesPerRow: 256 }, size, {
+ dataSize: offset + info.bytesPerBlock,
+ method,
+ success,
+ });
+ });
+
+g.test('bound_on_bytes_per_row')
+ .desc(
+ `
+Test that bytesPerRow, if specified must be big enough for a full copy row.
+- for various copy methods
+- for all sized formats
+- for all dimension
+- for various copy heights
+- for various copy depths
+- for various combinations of bytesPerRow and copy width.
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('copyHeightInBlocks', [1, 2])
+ .combine('copyDepth', [1, 2])
+ .unless(p => p.dimension === '1d' && (p.copyHeightInBlocks > 1 || p.copyDepth > 1))
+ .expandWithParams(p => {
+ const info = kTextureFormatInfo[p.format];
+ // We currently have a built-in assumption that for all formats, 128 % bytesPerBlock === 0.
+ // This assumption ensures that all division below results in integers.
+ assert(128 % info.bytesPerBlock === 0);
+ return [
+ // Copying exact fit with aligned bytesPerRow should work.
+ {
+ bytesPerRow: 256,
+ widthInBlocks: 256 / info.bytesPerBlock,
+ copyWidthInBlocks: 256 / info.bytesPerBlock,
+ _success: true,
+ },
+ // Copying into smaller texture when padding in bytesPerRow is enough should work unless
+ // it is a depth/stencil typed format.
+ {
+ bytesPerRow: 256,
+ widthInBlocks: 256 / info.bytesPerBlock,
+ copyWidthInBlocks: 256 / info.bytesPerBlock - 1,
+ _success: !(info.stencil || info.depth),
+ },
+ // Unaligned bytesPerRow should not work unless the method is 'WriteTexture'.
+ {
+ bytesPerRow: 128,
+ widthInBlocks: 128 / info.bytesPerBlock,
+ copyWidthInBlocks: 128 / info.bytesPerBlock,
+ _success: p.method === 'WriteTexture',
+ },
+ {
+ bytesPerRow: 384,
+ widthInBlocks: 384 / info.bytesPerBlock,
+ copyWidthInBlocks: 384 / info.bytesPerBlock,
+ _success: p.method === 'WriteTexture',
+ },
+ // When bytesPerRow is smaller than bytesInLastRow copying should fail.
+ {
+ bytesPerRow: 256,
+ widthInBlocks: (2 * 256) / info.bytesPerBlock,
+ copyWidthInBlocks: (2 * 256) / info.bytesPerBlock,
+ _success: false,
+ },
+ // When copyHeightInBlocks > 1, bytesPerRow must be specified.
+ {
+ bytesPerRow: undefined,
+ widthInBlocks: 256 / info.bytesPerBlock,
+ copyWidthInBlocks: 256 / info.bytesPerBlock,
+ _success: !(p.copyHeightInBlocks > 1 || p.copyDepth > 1),
+ },
+ ];
+ })
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ method,
+ format,
+ bytesPerRow,
+ widthInBlocks,
+ copyWidthInBlocks,
+ copyHeightInBlocks,
+ copyDepth,
+ _success,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ // We create an aligned texture using the widthInBlocks which may be different from the
+ // copyWidthInBlocks. This allows us to test scenarios where the two may be different.
+ const texture = t.createAlignedTexture(format, {
+ width: widthInBlocks * info.blockWidth,
+ height: copyHeightInBlocks * info.blockHeight,
+ depthOrArrayLayers: copyDepth,
+ });
+
+ const layout = { bytesPerRow, rowsPerImage: copyHeightInBlocks };
+ const copySize = {
+ width: copyWidthInBlocks * info.blockWidth,
+ height: copyHeightInBlocks * info.blockHeight,
+ depthOrArrayLayers: copyDepth,
+ };
+ const { minDataSizeOrOverestimate } = dataBytesForCopyOrOverestimate({
+ layout,
+ format,
+ copySize,
+ method,
+ });
+
+ t.testRun({ texture }, layout, copySize, {
+ dataSize: minDataSizeOrOverestimate,
+ method,
+ success: _success,
+ });
+ });
+
+g.test('bound_on_offset')
+ .desc(
+ `
+Test that the offset cannot be larger than the linear data size (even for an empty copy).
+- for various offsets and data sizes
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .beginSubcases()
+ .combine('offsetInBlocks', [0, 1, 2])
+ .combine('dataSizeInBlocks', [0, 1, 2])
+ )
+ .fn(async t => {
+ const { offsetInBlocks, dataSizeInBlocks, method } = t.params;
+
+ const format = 'rgba8unorm';
+ const info = kTextureFormatInfo[format];
+ const offset = offsetInBlocks * info.bytesPerBlock;
+ const dataSize = dataSizeInBlocks * info.bytesPerBlock;
+
+ const texture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const success = offset <= dataSize;
+
+ t.testRun(
+ { texture },
+ { offset, bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize, method, success }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js
new file mode 100644
index 0000000000..0189f028b0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/image_copy/texture_related.spec.js
@@ -0,0 +1,541 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Texture related validation tests for B2T copy and T2B copy and writeTexture.`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/util/util.js';
+import {
+ kColorTextureFormats,
+ kSizedTextureFormats,
+ kTextureDimensions,
+ kTextureFormatInfo,
+ kTextureUsages,
+ textureDimensionAndFormatCompatible,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { kResourceStates } from '../../../gpu_test.js';
+import { align } from '../../../util/math.js';
+import { virtualMipSize } from '../../../util/texture/base.js';
+import { kImageCopyTypes } from '../../../util/texture/layout.js';
+
+import {
+ ImageCopyTest,
+ texelBlockAlignmentTestExpanderForValueToCoordinate,
+ formatCopyableWithMethod,
+ getACopyableAspectWithMethod,
+} from './image_copy.js';
+
+export const g = makeTestGroup(ImageCopyTest);
+
+g.test('valid')
+ .desc(
+ `
+Test that the texture must be valid and not destroyed.
+- for all copy methods
+- for all texture states
+- for various dimensions
+`
+ )
+ .params(u =>
+ u //
+ .combine('method', kImageCopyTypes)
+ .combine('textureState', kResourceStates)
+ .combineWithParams([
+ { dimension: '1d', size: [4, 1, 1] },
+ { dimension: '2d', size: [4, 4, 1] },
+ { dimension: '2d', size: [4, 4, 3] },
+ { dimension: '3d', size: [4, 4, 3] },
+ ])
+ )
+ .fn(async t => {
+ const { method, textureState, size, dimension } = t.params;
+
+ const texture = t.createTextureWithState(textureState, {
+ size,
+ dimension,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const success = textureState === 'valid';
+ const submit = textureState !== 'invalid';
+
+ t.testRun(
+ { texture },
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 1, method, success, submit }
+ );
+ });
+
+g.test('texture,device_mismatch')
+ .desc('Tests the image copies cannot be called with a texture created from another device')
+ .paramsSubcasesOnly(u =>
+ u.combine('method', kImageCopyTypes).combine('mismatched', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { method, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const texture = sourceDevice.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ t.testRun(
+ { texture },
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 1, method, success: !mismatched }
+ );
+ });
+
+g.test('usage')
+ .desc(
+ `
+The texture must have the appropriate COPY_SRC/COPY_DST usage.
+- for various copy methods
+- for various dimensions
+- for various usages
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combineWithParams([
+ { dimension: '1d', size: [4, 1, 1] },
+ { dimension: '2d', size: [4, 4, 1] },
+ { dimension: '2d', size: [4, 4, 3] },
+ { dimension: '3d', size: [4, 4, 3] },
+ ])
+ .beginSubcases()
+ // 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)
+ // RENDER_ATTACHMENT is not valid with 1d and 3d textures.
+ .unless(
+ ({ usage0, usage1, dimension }) =>
+ ((usage0 | usage1) & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 &&
+ (dimension === '1d' || dimension === '3d')
+ )
+ )
+ .fn(async t => {
+ const { usage0, usage1, method, size, dimension } = t.params;
+
+ const usage = usage0 | usage1;
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ format: 'rgba8unorm',
+ usage,
+ });
+
+ const success =
+ method === 'CopyT2B'
+ ? (usage & GPUTextureUsage.COPY_SRC) !== 0
+ : (usage & GPUTextureUsage.COPY_DST) !== 0;
+
+ t.testRun(
+ { texture },
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 1, method, success }
+ );
+ });
+
+g.test('sample_count')
+ .desc(
+ `
+Test that multisampled textures cannot be copied.
+- for various copy methods
+- multisampled or not
+
+Note: we don't test 1D, 2D array and 3D textures because multisample is not supported them.
+`
+ )
+ .params(u =>
+ u //
+ .combine('method', kImageCopyTypes)
+ .beginSubcases()
+ .combine('sampleCount', [1, 4])
+ )
+ .fn(async t => {
+ const { sampleCount, method } = t.params;
+
+ const texture = t.device.createTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ sampleCount,
+ format: 'rgba8unorm',
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const success = sampleCount === 1;
+
+ t.testRun(
+ { texture },
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 1, method, success }
+ );
+ });
+
+g.test('mip_level')
+ .desc(
+ `
+Test that the mipLevel of the copy must be in range of the texture.
+- for various copy methods
+- for various dimensions
+- for several mipLevelCounts
+- for several target/source mipLevels`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combineWithParams([
+ { dimension: '1d', size: [32, 1, 1] },
+ { dimension: '2d', size: [32, 32, 1] },
+ { dimension: '2d', size: [32, 32, 3] },
+ { dimension: '3d', size: [32, 32, 3] },
+ ])
+ .beginSubcases()
+ .combine('mipLevelCount', [1, 3, 5])
+ .unless(p => p.dimension === '1d' && p.mipLevelCount !== 1)
+ .combine('mipLevel', [0, 1, 3, 4])
+ )
+ .fn(async t => {
+ const { mipLevelCount, mipLevel, method, size, dimension } = t.params;
+
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ mipLevelCount,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const success = mipLevel < mipLevelCount;
+
+ t.testRun(
+ { texture, mipLevel },
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 1, method, success }
+ );
+ });
+
+g.test('format')
+ .desc(
+ `
+Test the copy must be a full subresource if the texture's format is depth/stencil format.
+- for various copy methods
+- for various dimensions
+- for all sized formats
+- for a couple target/source mipLevels
+- for some modifier (or not) for the full copy size
+`
+ )
+ .params(u =>
+ u //
+ .combine('method', kImageCopyTypes)
+ .combineWithParams([
+ { depthOrArrayLayers: 1, dimension: '1d' },
+ { depthOrArrayLayers: 1, dimension: '2d' },
+ { depthOrArrayLayers: 3, dimension: '2d' },
+ { depthOrArrayLayers: 32, dimension: '3d' },
+ ])
+ .combine('format', kSizedTextureFormats)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .filter(formatCopyableWithMethod)
+ .beginSubcases()
+ .combine('mipLevel', [0, 2])
+ .unless(p => p.dimension === '1d' && p.mipLevel !== 0)
+ .combine('copyWidthModifier', [0, -1])
+ .combine('copyHeightModifier', [0, -1])
+ // If the texture has multiple depth/array slices and it is not a 3D texture, which means it is an array texture,
+ // depthModifier is not needed upon the third dimension. Because different layers are different subresources in
+ // an array texture. Whether it is a full copy or non-full copy doesn't make sense across different subresources.
+ // However, different depth slices on the same mip level are within the same subresource for a 3d texture. So we
+ // need to examine depth dimension via copyDepthModifier to determine whether it is a full copy for a 3D texture.
+ .expand('copyDepthModifier', ({ dimension: d }) => (d === '3d' ? [0, -1] : [0]))
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ method,
+ depthOrArrayLayers,
+ dimension,
+ format,
+ mipLevel,
+ copyWidthModifier,
+ copyHeightModifier,
+ copyDepthModifier,
+ } = t.params;
+
+ const info = kTextureFormatInfo[format];
+ const size = { width: 32 * info.blockWidth, height: 32 * info.blockHeight, depthOrArrayLayers };
+ if (dimension === '1d') {
+ size.height = 1;
+ }
+
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ format,
+ mipLevelCount: dimension === '1d' ? 1 : 5,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ let success = true;
+ if (
+ (info.depth || info.stencil) &&
+ (copyWidthModifier !== 0 || copyHeightModifier !== 0 || copyDepthModifier !== 0)
+ ) {
+ success = false;
+ }
+
+ const levelSize = virtualMipSize(
+ dimension,
+ [size.width, size.height, size.depthOrArrayLayers],
+ mipLevel
+ );
+
+ const copySize = [
+ levelSize[0] + copyWidthModifier * info.blockWidth,
+ levelSize[1] + copyHeightModifier * info.blockHeight,
+ // Note that compressed format is not supported for 3D textures yet, so there is no info.blockDepth.
+ levelSize[2] + copyDepthModifier,
+ ];
+
+ t.testRun(
+ { texture, mipLevel, aspect: getACopyableAspectWithMethod({ format, method }) },
+ { bytesPerRow: 512, rowsPerImage: 32 },
+ copySize,
+ {
+ dataSize: 512 * 32 * 32,
+ method,
+ success,
+ }
+ );
+ });
+
+g.test('origin_alignment')
+ .desc(
+ `
+Test that the texture copy origin must be aligned to the format's block size.
+- for various copy methods
+- for all color formats (depth stencil formats require a full copy)
+- for X, Y and Z coordinates
+- for various values for that coordinate depending on the block size
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ // No need to test depth/stencil formats because its copy origin must be [0, 0, 0], which is already aligned with block size.
+ .combine('format', kColorTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combineWithParams([
+ { depthOrArrayLayers: 1, dimension: '1d' },
+ { depthOrArrayLayers: 1, dimension: '2d' },
+ { depthOrArrayLayers: 3, dimension: '2d' },
+ { depthOrArrayLayers: 3, dimension: '3d' },
+ ])
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('coordinateToTest', ['x', 'y', 'z'])
+ .unless(p => p.dimension === '1d' && p.coordinateToTest !== 'x')
+ .expand('valueToCoordinate', texelBlockAlignmentTestExpanderForValueToCoordinate)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ valueToCoordinate,
+ coordinateToTest,
+ format,
+ method,
+ depthOrArrayLayers,
+ dimension,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+ const size = { width: 0, height: 0, depthOrArrayLayers };
+ const origin = { x: 0, y: 0, z: 0 };
+ let success = true;
+
+ origin[coordinateToTest] = valueToCoordinate;
+ switch (coordinateToTest) {
+ case 'x': {
+ success = origin.x % info.blockWidth === 0;
+ break;
+ }
+ case 'y': {
+ success = origin.y % info.blockHeight === 0;
+ break;
+ }
+ }
+
+ const texture = t.createAlignedTexture(format, size, origin, dimension);
+
+ t.testRun({ texture, origin }, { bytesPerRow: 0, rowsPerImage: 0 }, size, {
+ dataSize: 1,
+ method,
+ success,
+ });
+ });
+
+g.test('size_alignment')
+ .desc(
+ `
+Test that the copy size must be aligned to the texture's format's block size.
+- for various copy methods
+- for all formats (depth-stencil formats require a full copy)
+- for all texture dimensions
+- for the size's parameters to test (width / height / depth)
+- for various values for that copy size parameters, depending on the block size
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ // No need to test depth/stencil formats because its copy size must be subresource's size, which is already aligned with block size.
+ .combine('format', kColorTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('coordinateToTest', ['width', 'height', 'depthOrArrayLayers'])
+ .unless(p => p.dimension === '1d' && p.coordinateToTest !== 'width')
+ .expand('valueToCoordinate', texelBlockAlignmentTestExpanderForValueToCoordinate)
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { valueToCoordinate, coordinateToTest, dimension, format, method } = t.params;
+ const info = kTextureFormatInfo[format];
+ const size = { width: 0, height: 0, depthOrArrayLayers: 0 };
+ const origin = { x: 0, y: 0, z: 0 };
+ let success = true;
+
+ size[coordinateToTest] = valueToCoordinate;
+ switch (coordinateToTest) {
+ case 'width': {
+ success = size.width % info.blockWidth === 0;
+ break;
+ }
+ case 'height': {
+ success = size.height % info.blockHeight === 0;
+ break;
+ }
+ }
+
+ const texture = t.createAlignedTexture(format, size, origin, dimension);
+
+ const bytesPerRow = align(
+ Math.max(1, Math.ceil(size.width / info.blockWidth)) * info.bytesPerBlock,
+ 256
+ );
+
+ const rowsPerImage = Math.ceil(size.height / info.blockHeight);
+ t.testRun({ texture, origin }, { bytesPerRow, rowsPerImage }, size, {
+ dataSize: 1,
+ method,
+ success,
+ });
+ });
+
+g.test('copy_rectangle')
+ .desc(
+ `
+Test that the max corner of the copy rectangle (origin+copySize) must be inside the texture.
+- for various copy methods
+- for all dimensions
+- for the X, Y and Z dimensions
+- for various origin and copy size values (and texture sizes)
+- for various mip levels
+`
+ )
+ .params(u =>
+ u
+ .combine('method', kImageCopyTypes)
+ .combine('dimension', kTextureDimensions)
+ .beginSubcases()
+ .combine('originValue', [7, 8])
+ .combine('copySizeValue', [7, 8])
+ .combine('textureSizeValue', [14, 15])
+ .combine('mipLevel', [0, 2])
+ .combine('coordinateToTest', [0, 1, 2])
+ .unless(p => p.dimension === '1d' && (p.coordinateToTest !== 0 || p.mipLevel !== 0))
+ )
+ .fn(async t => {
+ const {
+ originValue,
+ copySizeValue,
+ textureSizeValue,
+ mipLevel,
+ coordinateToTest,
+ method,
+ dimension,
+ } = t.params;
+ const format = 'rgba8unorm';
+ const info = kTextureFormatInfo[format];
+
+ const origin = [0, 0, 0];
+ const copySize = [0, 0, 0];
+ const textureSize = { width: 16 << mipLevel, height: 16 << mipLevel, depthOrArrayLayers: 16 };
+ if (dimension === '1d') {
+ textureSize.height = 1;
+ textureSize.depthOrArrayLayers = 1;
+ }
+ const success = originValue + copySizeValue <= textureSizeValue;
+
+ origin[coordinateToTest] = originValue;
+ copySize[coordinateToTest] = copySizeValue;
+ switch (coordinateToTest) {
+ case 0: {
+ textureSize.width = textureSizeValue << mipLevel;
+ break;
+ }
+ case 1: {
+ textureSize.height = textureSizeValue << mipLevel;
+ break;
+ }
+ case 2: {
+ textureSize.depthOrArrayLayers =
+ dimension === '3d' ? textureSizeValue << mipLevel : textureSizeValue;
+ break;
+ }
+ }
+
+ const texture = t.device.createTexture({
+ size: textureSize,
+ dimension,
+ mipLevelCount: dimension === '1d' ? 1 : 3,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ assert(copySize[0] % info.blockWidth === 0);
+ const bytesPerRow = align(copySize[0] / info.blockWidth, 256);
+ assert(copySize[1] % info.blockHeight === 0);
+ const rowsPerImage = copySize[1] / info.blockHeight;
+ t.testRun({ texture, origin, mipLevel }, { bytesPerRow, rowsPerImage }, copySize, {
+ dataSize: 1,
+ method,
+ success,
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js
new file mode 100644
index 0000000000..376d30f3ff
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/layout_shader_compat.spec.js
@@ -0,0 +1,15 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+TODO:
+- interface matching between pipeline layout and shader
+ - x= {compute, vertex, fragment, vertex+fragment}, visibilities
+ - x= bind group index values, binding index values, multiple bindings
+ - x= types of bindings
+ - x= {equal, superset, subset}
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+import { ValidationTest } from './validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/create.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/create.spec.js
new file mode 100644
index 0000000000..0119628759
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/create.spec.js
@@ -0,0 +1,35 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for validation in createQuerySet.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kQueryTypes, kMaxQueryCount } from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('count')
+ .desc(
+ `
+Tests that create query set with the count for all query types:
+- count {<, =, >} kMaxQueryCount
+- x= {occlusion, timestamp} query
+ `
+ )
+ .params(u =>
+ u
+ .combine('type', kQueryTypes)
+ .beginSubcases()
+ .combine('count', [0, kMaxQueryCount, kMaxQueryCount + 1])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForQueryTypeOrSkipTestCase(t.params.type);
+ })
+ .fn(async t => {
+ const { type, count } = t.params;
+
+ t.expectValidationError(() => {
+ t.device.createQuerySet({ type, count });
+ }, count > kMaxQueryCount);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/destroy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/destroy.spec.js
new file mode 100644
index 0000000000..cb9101437f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/query_set/destroy.spec.js
@@ -0,0 +1,16 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Destroying a query set more than once is allowed.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('twice').fn(async t => {
+ const qset = t.device.createQuerySet({ type: 'occlusion', count: 1 });
+
+ qset.destroy();
+ qset.destroy();
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/buffer_mapped.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/buffer_mapped.spec.js
new file mode 100644
index 0000000000..1e662809f0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/buffer_mapped.spec.js
@@ -0,0 +1,266 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for the map-state of mappable buffers used in submitted command buffers.
+
+Tests every operation that has a dependency on a buffer
+ - writeBuffer
+ - copyB2B {src,dst}
+ - copyB2T
+ - copyT2B
+
+Test those operations against buffers in the following states:
+ - Unmapped
+ - In the process of mapping
+ - mapped
+ - mapped with a mapped range queried
+ - unmapped after mapping
+ - mapped at creation
+
+Also tests every order of operations combination of mapping operations and command recording
+operations to ensure the mapping state is only considered when a command buffer is submitted.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+class F extends ValidationTest {
+ async runBufferDependencyTest(usage, callback) {
+ const bufferDesc = {
+ size: 8,
+ usage,
+ mappedAtCreation: false,
+ };
+
+ const mapMode = usage & GPUBufferUsage.MAP_READ ? GPUMapMode.READ : GPUMapMode.WRITE;
+
+ // Create a mappable buffer, and one that will remain unmapped for comparison.
+ const mappableBuffer = this.device.createBuffer(bufferDesc);
+ const unmappedBuffer = this.device.createBuffer(bufferDesc);
+
+ // Run the given operation before the buffer is mapped. Should succeed.
+ callback(mappableBuffer);
+
+ // Map the buffer
+ const mapPromise = mappableBuffer.mapAsync(mapMode);
+
+ // Run the given operation while the buffer is in the process of mapping. Should fail.
+ this.expectValidationError(() => {
+ callback(mappableBuffer);
+ });
+
+ // Run on a different, unmapped buffer. Should succeed.
+ callback(unmappedBuffer);
+
+ await mapPromise;
+
+ // Run the given operation when the buffer is finished mapping with no getMappedRange. Should fail.
+ this.expectValidationError(() => {
+ callback(mappableBuffer);
+ });
+
+ // Run on a different, unmapped buffer. Should succeed.
+ callback(unmappedBuffer);
+
+ // Run the given operation when the buffer is mapped with getMappedRange. Should fail.
+ mappableBuffer.getMappedRange();
+ this.expectValidationError(() => {
+ callback(mappableBuffer);
+ });
+
+ // Unmap the buffer and run the operation. Should succeed.
+ mappableBuffer.unmap();
+ callback(mappableBuffer);
+
+ // Create a buffer that's mappedAtCreation.
+ bufferDesc.mappedAtCreation = true;
+ const mappedBuffer = this.device.createBuffer(bufferDesc);
+
+ // Run the operation with the mappedAtCreation buffer. Should fail.
+ this.expectValidationError(() => {
+ callback(mappedBuffer);
+ });
+
+ // Run on a different, unmapped buffer. Should succeed.
+ callback(unmappedBuffer);
+
+ // Unmap the mappedAtCreation buffer and run the operation. Should succeed.
+ mappedBuffer.unmap();
+ callback(mappedBuffer);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('writeBuffer')
+ .desc(`Test that an outstanding mapping will prevent writeBuffer calls.`)
+ .fn(async t => {
+ const data = new Uint32Array([42]);
+
+ await t.runBufferDependencyTest(GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, buffer => {
+ t.queue.writeBuffer(buffer, 0, data);
+ });
+ });
+
+g.test('copyBufferToBuffer')
+ .desc(
+ `
+ Test that an outstanding mapping will prevent copyBufferToTexture commands from submitting,
+ both when used as the source and destination.`
+ )
+ .fn(async t => {
+ const sourceBuffer = t.device.createBuffer({
+ size: 8,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+
+ const destBuffer = t.device.createBuffer({
+ size: 8,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ await t.runBufferDependencyTest(GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC, buffer => {
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.copyBufferToBuffer(buffer, 0, destBuffer, 0, 4);
+ t.queue.submit([commandEncoder.finish()]);
+ });
+
+ await t.runBufferDependencyTest(GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, buffer => {
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.copyBufferToBuffer(sourceBuffer, 0, buffer, 0, 4);
+ t.queue.submit([commandEncoder.finish()]);
+ });
+ });
+
+g.test('copyBufferToTexture')
+ .desc(
+ `Test that an outstanding mapping will prevent copyBufferToTexture commands from submitting.`
+ )
+ .fn(async t => {
+ const size = { width: 1, height: 1 };
+
+ const texture = t.device.createTexture({
+ size,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ await t.runBufferDependencyTest(GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC, buffer => {
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.copyBufferToTexture({ buffer }, { texture }, size);
+ t.queue.submit([commandEncoder.finish()]);
+ });
+ });
+
+g.test('copyTextureToBuffer')
+ .desc(
+ `Test that an outstanding mapping will prevent copyTextureToBuffer commands from submitting.`
+ )
+ .fn(async t => {
+ const size = { width: 1, height: 1 };
+
+ const texture = t.device.createTexture({
+ size,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC,
+ });
+
+ await t.runBufferDependencyTest(GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, buffer => {
+ const commandEncoder = t.device.createCommandEncoder();
+ commandEncoder.copyTextureToBuffer({ texture }, { buffer }, size);
+ t.queue.submit([commandEncoder.finish()]);
+ });
+ });
+
+g.test('map_command_recording_order')
+ .desc(
+ `
+Test that the order of mapping a buffer relative to when commands are recorded that use it
+ does not matter, as long as the buffer is unmapped when the commands are submitted.
+ `
+ )
+ .paramsSubcasesOnly([
+ {
+ order: ['record', 'map', 'unmap', 'finish', 'submit'],
+ mappedAtCreation: false,
+ _shouldError: false,
+ },
+ {
+ order: ['record', 'map', 'finish', 'unmap', 'submit'],
+ mappedAtCreation: false,
+ _shouldError: false,
+ },
+ {
+ order: ['record', 'finish', 'map', 'unmap', 'submit'],
+ mappedAtCreation: false,
+ _shouldError: false,
+ },
+ {
+ order: ['map', 'record', 'unmap', 'finish', 'submit'],
+ mappedAtCreation: false,
+ _shouldError: false,
+ },
+ {
+ order: ['map', 'record', 'finish', 'unmap', 'submit'],
+ mappedAtCreation: false,
+ _shouldError: false,
+ },
+ {
+ order: ['map', 'record', 'finish', 'submit', 'unmap'],
+ mappedAtCreation: false,
+ _shouldError: true,
+ },
+ {
+ order: ['record', 'map', 'finish', 'submit', 'unmap'],
+ mappedAtCreation: false,
+ _shouldError: true,
+ },
+ {
+ order: ['record', 'finish', 'map', 'submit', 'unmap'],
+ mappedAtCreation: false,
+ _shouldError: true,
+ },
+ { order: ['record', 'unmap', 'finish', 'submit'], mappedAtCreation: true, _shouldError: false },
+ { order: ['record', 'finish', 'unmap', 'submit'], mappedAtCreation: true, _shouldError: false },
+ { order: ['record', 'finish', 'submit', 'unmap'], mappedAtCreation: true, _shouldError: true },
+ ])
+ .fn(async t => {
+ const { order, mappedAtCreation, _shouldError: shouldError } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,
+ mappedAtCreation,
+ });
+
+ const targetBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+
+ const commandEncoder = t.device.createCommandEncoder();
+ let commandBuffer;
+
+ const steps = {
+ record: async () => {
+ commandEncoder.copyBufferToBuffer(buffer, 0, targetBuffer, 0, 4);
+ },
+ map: async () => {
+ await buffer.mapAsync(GPUMapMode.WRITE);
+ },
+ unmap: async () => {
+ buffer.unmap();
+ },
+ finish: async () => {
+ commandBuffer = commandEncoder.finish();
+ },
+ submit: async () => {
+ t.expectValidationError(() => {
+ t.queue.submit([commandBuffer]);
+ }, shouldError);
+ },
+ };
+
+ for (const op of order) {
+ await steps[op]();
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js
new file mode 100644
index 0000000000..61a572a0fe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.js
@@ -0,0 +1,886 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyExternalImageToTexture Validation Tests in Queue.
+Note that we don't need to add tests on the destination texture dimension as currently we require
+the destination texture should have RENDER_ATTACHMENT usage, which is only allowed to be used on 2D
+textures.
+`;
+import {
+ getResourcePath,
+ getCrossOriginResourcePath,
+} from '../../../../../common/framework/resources.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { raceWithRejectOnTimeout, unreachable, assert } from '../../../../../common/util/util.js';
+import {
+ kTextureFormatInfo,
+ kTextureFormats,
+ kTextureUsages,
+ kValidTextureFormatsForCopyE2T,
+} from '../../../../capability_info.js';
+import { kResourceStates } from '../../../../gpu_test.js';
+import {
+ canCopyFromCanvasContext,
+ createCanvas,
+ createOnscreenCanvas,
+ createOffscreenCanvas,
+ kValidCanvasContextIds,
+} from '../../../../util/create_elements.js';
+import { ValidationTest } from '../../validation_test.js';
+
+const kDefaultBytesPerPixel = 4; // using 'bgra8unorm' or 'rgba8unorm'
+const kDefaultWidth = 32;
+const kDefaultHeight = 32;
+const kDefaultDepth = 1;
+const kDefaultMipLevelCount = 6;
+
+function computeMipMapSize(width, height, mipLevel) {
+ return {
+ mipWidth: Math.max(width >> mipLevel, 1),
+ mipHeight: Math.max(height >> mipLevel, 1),
+ };
+}
+
+// Helper function to generate copySize for src OOB test
+function generateCopySizeForSrcOOB({ srcOrigin }) {
+ // OOB origin fails even with no-op copy.
+ if (srcOrigin.x > kDefaultWidth || srcOrigin.y > kDefaultHeight) {
+ return [{ width: 0, height: 0, depthOrArrayLayers: 0 }];
+ }
+
+ const justFitCopySize = {
+ width: kDefaultWidth - srcOrigin.x,
+ height: kDefaultHeight - srcOrigin.y,
+ depthOrArrayLayers: 1,
+ };
+
+ return [
+ justFitCopySize, // correct size, maybe no-op copy.
+ {
+ width: justFitCopySize.width + 1,
+ height: justFitCopySize.height,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers,
+ }, // OOB in width
+ {
+ width: justFitCopySize.width,
+ height: justFitCopySize.height + 1,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers,
+ }, // OOB in height
+ {
+ width: justFitCopySize.width,
+ height: justFitCopySize.height,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers + 1,
+ }, // OOB in depthOrArrayLayers
+ ];
+}
+
+// Helper function to generate dst origin value based on mipLevel.
+function generateDstOriginValue({ mipLevel }) {
+ const origin = computeMipMapSize(kDefaultWidth, kDefaultHeight, mipLevel);
+
+ return [
+ { x: 0, y: 0, z: 0 },
+ { x: origin.mipWidth - 1, y: 0, z: 0 },
+ { x: 0, y: origin.mipHeight - 1, z: 0 },
+ { x: origin.mipWidth, y: 0, z: 0 },
+ { x: 0, y: origin.mipHeight, z: 0 },
+ { x: 0, y: 0, z: kDefaultDepth },
+ { x: origin.mipWidth + 1, y: 0, z: 0 },
+ { x: 0, y: origin.mipHeight + 1, z: 0 },
+ { x: 0, y: 0, z: kDefaultDepth + 1 },
+ ];
+}
+
+// Helper function to generate copySize for dst OOB test
+function generateCopySizeForDstOOB({ mipLevel, dstOrigin }) {
+ const dstMipMapSize = computeMipMapSize(kDefaultWidth, kDefaultHeight, mipLevel);
+
+ // OOB origin fails even with no-op copy.
+ if (
+ dstOrigin.x > dstMipMapSize.mipWidth ||
+ dstOrigin.y > dstMipMapSize.mipHeight ||
+ dstOrigin.z > kDefaultDepth
+ ) {
+ return [{ width: 0, height: 0, depthOrArrayLayers: 0 }];
+ }
+
+ const justFitCopySize = {
+ width: dstMipMapSize.mipWidth - dstOrigin.x,
+ height: dstMipMapSize.mipHeight - dstOrigin.y,
+ depthOrArrayLayers: kDefaultDepth - dstOrigin.z,
+ };
+
+ return [
+ justFitCopySize,
+ {
+ width: justFitCopySize.width + 1,
+ height: justFitCopySize.height,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers,
+ }, // OOB in width
+ {
+ width: justFitCopySize.width,
+ height: justFitCopySize.height + 1,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers,
+ }, // OOB in height
+ {
+ width: justFitCopySize.width,
+ height: justFitCopySize.height,
+ depthOrArrayLayers: justFitCopySize.depthOrArrayLayers + 1,
+ }, // OOB in depthOrArrayLayers
+ ];
+}
+
+class CopyExternalImageToTextureTest extends ValidationTest {
+ onlineCrossOriginUrl = 'https://raw.githubusercontent.com/gpuweb/gpuweb/main/logo/webgpu.png';
+
+ getImageData(width, height) {
+ if (typeof ImageData === 'undefined') {
+ this.skip('ImageData is not supported.');
+ }
+
+ const pixelSize = kDefaultBytesPerPixel * width * height;
+ const imagePixels = new Uint8ClampedArray(pixelSize);
+ return new ImageData(imagePixels, width, height);
+ }
+
+ getCanvasWithContent(canvasType, width, height, content) {
+ const canvas = createCanvas(this, canvasType, 1, 1);
+ const ctx = canvas.getContext('2d');
+ assert(ctx !== null);
+ ctx.drawImage(content, 0, 0);
+
+ return canvas;
+ }
+
+ createImageBitmap(image) {
+ if (typeof createImageBitmap === 'undefined') {
+ this.skip('Creating ImageBitmaps is not supported.');
+ }
+ return createImageBitmap(image);
+ }
+
+ runTest(imageBitmapCopyView, textureCopyView, copySize, validationScopeSuccess, exceptionName) {
+ // copyExternalImageToTexture will generate two types of errors. One is synchronous exceptions;
+ // the other is asynchronous validation error scope errors.
+ if (exceptionName) {
+ this.shouldThrow(exceptionName, () => {
+ this.device.queue.copyExternalImageToTexture(
+ imageBitmapCopyView,
+ textureCopyView,
+ copySize
+ );
+ });
+ } else {
+ this.expectValidationError(() => {
+ this.device.queue.copyExternalImageToTexture(
+ imageBitmapCopyView,
+ textureCopyView,
+ copySize
+ );
+ }, !validationScopeSuccess);
+ }
+ }
+}
+
+export const g = makeTestGroup(CopyExternalImageToTextureTest);
+
+g.test('source_canvas,contexts')
+ .desc(
+ `
+ Test HTMLCanvasElement as source image with different contexts.
+
+ Call HTMLCanvasElement.getContext() with different context type.
+ Only '2d', 'experimental-webgl', 'webgl', 'webgl2' is valid context
+ type.
+
+ Check whether 'OperationError' is generated when context type is invalid.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('contextType', kValidCanvasContextIds)
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { contextType, copySize } = t.params;
+ const canvas = createOnscreenCanvas(t, 1, 1);
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const ctx = canvas.getContext(contextType);
+ if (ctx === null) {
+ t.skip('Failed to get context for canvas element');
+ return;
+ }
+ t.tryTrackForCleanup(ctx);
+
+ t.runTest(
+ { source: canvas },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ canCopyFromCanvasContext(contextType) ? '' : 'OperationError'
+ );
+ });
+
+g.test('source_offscreenCanvas,contexts')
+ .desc(
+ `
+ Test OffscreenCanvas as source image with different contexts.
+
+ Call OffscreenCanvas.getContext() with different context type.
+ Only '2d', 'webgl', 'webgl2', 'webgpu' is valid context type.
+
+ Check whether 'OperationError' is generated when context type is invalid.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('contextType', kValidCanvasContextIds)
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { contextType, copySize } = t.params;
+ const canvas = createOffscreenCanvas(t, 1, 1);
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ // MAINTENANCE_TODO: Workaround for @types/offscreencanvas missing an overload of
+ // `OffscreenCanvas.getContext` that takes `string` or a union of context types.
+ const ctx = canvas.getContext(contextType);
+
+ if (ctx === null) {
+ t.skip('Failed to get context for canvas element');
+ return;
+ }
+ t.tryTrackForCleanup(ctx);
+
+ t.runTest(
+ { source: canvas },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ canCopyFromCanvasContext(contextType) ? '' : 'OperationError'
+ );
+ });
+
+g.test('source_image,crossOrigin')
+ .desc(
+ `
+ Test contents of source image is [clean, cross-origin].
+
+ Load crossOrigin image or same origin image and init the source
+ images.
+
+ Check whether 'SecurityError' is generated when source image is not origin clean.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('sourceImage', ['canvas', 'offscreenCanvas', 'imageBitmap'])
+ .combine('isOriginClean', [true, false])
+ .beginSubcases()
+ .combine('contentFrom', ['image', 'imageBitmap', 'canvas', 'offscreenCanvas'])
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { sourceImage, isOriginClean, contentFrom, copySize } = t.params;
+ if (typeof document === 'undefined') {
+ t.skip('DOM is not available to create an image element.');
+ }
+
+ const crossOriginUrl = getCrossOriginResourcePath('webgpu.png', t.onlineCrossOriginUrl);
+ const originCleanUrl = getResourcePath('webgpu.png');
+ const img = document.createElement('img');
+ img.src = isOriginClean ? originCleanUrl : crossOriginUrl;
+
+ // Load image
+ const timeout_ms = 5000;
+ try {
+ await raceWithRejectOnTimeout(img.decode(), timeout_ms, 'load image timeout');
+ } catch (e) {
+ if (isOriginClean) {
+ throw e;
+ } else {
+ t.skip('Cannot load cross origin image in time');
+ return;
+ }
+ }
+
+ // The externalImage contents can be updated by:
+ // - decoded image element
+ // - canvas/offscreenCanvas with image draw on it.
+ // - imageBitmap created with the image.
+ // Test covers all of these cases to ensure origin clean checks works.
+ let source;
+ switch (contentFrom) {
+ case 'image': {
+ source = img;
+ break;
+ }
+ case 'imageBitmap': {
+ source = await t.createImageBitmap(img);
+ break;
+ }
+ case 'canvas':
+ case 'offscreenCanvas': {
+ const canvasType = contentFrom === 'offscreenCanvas' ? 'offscreen' : 'onscreen';
+ source = t.getCanvasWithContent(canvasType, 1, 1, img);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ // Update the externalImage content with source.
+ let externalImage;
+ switch (sourceImage) {
+ case 'imageBitmap': {
+ externalImage = await t.createImageBitmap(source);
+ break;
+ }
+ case 'canvas':
+ case 'offscreenCanvas': {
+ const canvasType = contentFrom === 'offscreenCanvas' ? 'offscreen' : 'onscreen';
+ externalImage = t.getCanvasWithContent(canvasType, 1, 1, source);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ t.runTest(
+ { source: externalImage },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ isOriginClean ? '' : 'SecurityError'
+ );
+ });
+
+g.test('source_imageBitmap,state')
+ .desc(
+ `
+ Test ImageBitmap as source image in state [valid, closed].
+
+ Call imageBitmap.close() to transfer the imageBitmap into
+ 'closed' state.
+
+ Check whether 'InvalidStateError' is generated when ImageBitmap is
+ closed.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('closed', [false, true])
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { closed, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ if (closed) imageBitmap.close();
+
+ t.runTest(
+ { source: imageBitmap },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ closed ? 'InvalidStateError' : ''
+ );
+ });
+
+g.test('source_canvas,state')
+ .desc(
+ `
+ Test HTMLCanvasElement as source image in state
+ [nocontext, 'placeholder-nocontext', 'placeholder-hascontext', valid].
+
+ Nocontext means using a canvas without any context as copy param.
+
+ Call 'transferControlToOffscreen' on HTMLCanvasElement will cause the
+ canvas control right transfer. And this canvas is in state 'placeholder'
+ Whether getContext in new generated offscreenCanvas won't affect the origin
+ canvas state.
+
+
+ Check whether 'OperationError' is generated when HTMLCanvasElement has no
+ context.
+
+ Check whether 'InvalidStateError' is generated when HTMLCanvasElement is
+ in 'placeholder' state.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('state', ['nocontext', 'placeholder-nocontext', 'placeholder-hascontext', 'valid'])
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { state, copySize } = t.params;
+ const canvas = createOnscreenCanvas(t, 1, 1);
+ if (typeof canvas.transferControlToOffscreen === 'undefined') {
+ t.skip("Browser doesn't support HTMLCanvasElement.transferControlToOffscreen");
+ return;
+ }
+
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ let exceptionName = '';
+
+ switch (state) {
+ case 'nocontext': {
+ exceptionName = 'OperationError';
+ break;
+ }
+ case 'placeholder-nocontext': {
+ canvas.transferControlToOffscreen();
+ exceptionName = 'InvalidStateError';
+ break;
+ }
+ case 'placeholder-hascontext': {
+ const offscreenCanvas = canvas.transferControlToOffscreen();
+ t.tryTrackForCleanup(offscreenCanvas.getContext('webgl'));
+ exceptionName = 'InvalidStateError';
+ break;
+ }
+ case 'valid': {
+ assert(canvas.getContext('2d') !== null);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ t.runTest(
+ { source: canvas },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ exceptionName
+ );
+ });
+
+g.test('source_offscreenCanvas,state')
+ .desc(
+ `
+ Test OffscreenCanvas as source image in state [valid, detached].
+
+ Nocontext means using a canvas without any context as copy param.
+
+ Transfer OffscreenCanvas with MessageChannel will detach the OffscreenCanvas.
+
+ Check whether 'OperationError' is generated when HTMLCanvasElement has no
+ context.
+
+ Check whether 'InvalidStateError' is generated when OffscreenCanvas is
+ detached.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('state', ['nocontext', 'detached-nocontext', 'detached-hascontext', 'valid'])
+ .beginSubcases()
+ .combine('getContextInOffscreenCanvas', [false, true])
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { state, copySize } = t.params;
+ const offscreenCanvas = createOffscreenCanvas(t, 1, 1);
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ let exceptionName = '';
+ switch (state) {
+ case 'nocontext': {
+ exceptionName = 'OperationError';
+ break;
+ }
+ case 'detached-nocontext': {
+ const messageChannel = new MessageChannel();
+ messageChannel.port1.postMessage(offscreenCanvas, [offscreenCanvas]);
+
+ exceptionName = 'InvalidStateError';
+ break;
+ }
+ case 'detached-hascontext': {
+ const messageChannel = new MessageChannel();
+ const port2FirstMessage = new Promise(resolve => {
+ messageChannel.port2.onmessage = m => resolve(m);
+ });
+
+ messageChannel.port1.postMessage(offscreenCanvas, [offscreenCanvas]);
+
+ const receivedOffscreenCanvas = await port2FirstMessage;
+ t.tryTrackForCleanup(receivedOffscreenCanvas.data.getContext('webgl'));
+
+ exceptionName = 'InvalidStateError';
+ break;
+ }
+ case 'valid': {
+ offscreenCanvas.getContext('webgl');
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ t.runTest(
+ { source: offscreenCanvas },
+ { texture: dstTexture },
+ copySize,
+ true, // No validation errors.
+ exceptionName
+ );
+ });
+
+g.test('destination_texture,state')
+ .desc(
+ `
+ Test dst texture is [valid, invalid, destroyed].
+
+ Check that an error is generated when texture is an error texture.
+ Check that an error is generated when texture is in destroyed state.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('state', kResourceStates)
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { state, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+ const dstTexture = t.createTextureWithState(state);
+
+ t.runTest({ source: imageBitmap }, { texture: dstTexture }, copySize, state === 'valid');
+ });
+
+g.test('destination_texture,device_mismatch')
+ .desc(
+ 'Tests copyExternalImageToTexture cannot be called with a destination texture created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+ const copySize = { width: 1, height: 1, depthOrArrayLayers: 1 };
+
+ const texture = sourceDevice.createTexture({
+ size: copySize,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+
+ t.runTest({ source: imageBitmap }, { texture }, copySize, !mismatched);
+ });
+
+g.test('destination_texture,usage')
+ .desc(
+ `
+ Test dst texture usages
+
+ Check that an error is generated when texture is created without usage COPY_DST | RENDER_ATTACHMENT.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('usage', kTextureUsages)
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { usage, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage,
+ });
+
+ t.runTest(
+ { source: imageBitmap },
+ { texture: dstTexture },
+ copySize,
+ !!(usage & GPUTextureUsage.COPY_DST && usage & GPUTextureUsage.RENDER_ATTACHMENT)
+ );
+ });
+
+g.test('destination_texture,sample_count')
+ .desc(
+ `
+ Test dst texture sample count.
+
+ Check that an error is generated when sample count it not 1.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('sampleCount', [1, 4])
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { sampleCount, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ sampleCount,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ t.runTest({ source: imageBitmap }, { texture: dstTexture }, copySize, sampleCount === 1);
+ });
+
+g.test('destination_texture,mipLevel')
+ .desc(
+ `
+ Test dst mipLevel.
+
+ Check that an error is generated when mipLevel is too large.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('mipLevel', [0, kDefaultMipLevelCount - 1, kDefaultMipLevelCount])
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .fn(async t => {
+ const { mipLevel, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+ const dstTexture = t.device.createTexture({
+ size: { width: kDefaultWidth, height: kDefaultHeight, depthOrArrayLayers: kDefaultDepth },
+ mipLevelCount: kDefaultMipLevelCount,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ t.runTest(
+ { source: imageBitmap },
+ { texture: dstTexture, mipLevel },
+ copySize,
+ mipLevel < kDefaultMipLevelCount
+ );
+ });
+
+g.test('destination_texture,format')
+ .desc(
+ `
+ Test dst texture format.
+
+ Check that an error is generated when texture format is not valid.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kTextureFormats)
+ .beginSubcases()
+ .combine('copySize', [
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { width: 1, height: 1, depthOrArrayLayers: 1 },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { format, copySize } = t.params;
+
+ const imageBitmap = await t.createImageBitmap(t.getImageData(1, 1));
+
+ // createTexture with all possible texture format may have validation error when using
+ // compressed texture format.
+ t.device.pushErrorScope('validation');
+ const dstTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ void t.device.popErrorScope();
+
+ const success = kValidTextureFormatsForCopyE2T.includes(format);
+
+ t.runTest({ source: imageBitmap }, { texture: dstTexture }, copySize, success);
+ });
+
+g.test('OOB,source')
+ .desc(
+ `
+ Test source image origin and copy size
+
+ Check that an error is generated when source.externalImage.origin + copySize is too large.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('srcOrigin', [
+ { x: 0, y: 0 }, // origin is on top-left
+ { x: kDefaultWidth - 1, y: 0 }, // x near the border
+ { x: 0, y: kDefaultHeight - 1 }, // y is near the border
+ { x: kDefaultWidth, y: kDefaultHeight }, // origin is on bottom-right
+ { x: kDefaultWidth + 1, y: 0 }, // x is too large
+ { x: 0, y: kDefaultHeight + 1 }, // y is too large
+ ])
+ .expand('copySize', generateCopySizeForSrcOOB)
+ )
+ .fn(async t => {
+ const { srcOrigin, copySize } = t.params;
+ const imageBitmap = await t.createImageBitmap(t.getImageData(kDefaultWidth, kDefaultHeight));
+ const dstTexture = t.device.createTexture({
+ size: {
+ width: kDefaultWidth + 1,
+ height: kDefaultHeight + 1,
+ depthOrArrayLayers: kDefaultDepth,
+ },
+ mipLevelCount: kDefaultMipLevelCount,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ let success = true;
+
+ if (
+ srcOrigin.x + copySize.width > kDefaultWidth ||
+ srcOrigin.y + copySize.height > kDefaultHeight ||
+ copySize.depthOrArrayLayers > 1
+ ) {
+ success = false;
+ }
+
+ t.runTest(
+ { source: imageBitmap, origin: srcOrigin },
+ { texture: dstTexture },
+ copySize,
+ true,
+ success ? '' : 'OperationError'
+ );
+ });
+
+g.test('OOB,destination')
+ .desc(
+ `
+ Test dst texture copy origin and copy size
+
+ Check that an error is generated when destination.texture.origin + copySize is too large.
+ Check that 'OperationError' is generated when copySize.depth is larger than 1.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('mipLevel', [0, 1, kDefaultMipLevelCount - 2])
+ .expand('dstOrigin', generateDstOriginValue)
+ .expand('copySize', generateCopySizeForDstOOB)
+ )
+ .fn(async t => {
+ const { mipLevel, dstOrigin, copySize } = t.params;
+
+ const imageBitmap = await t.createImageBitmap(
+ t.getImageData(kDefaultWidth + 1, kDefaultHeight + 1)
+ );
+
+ const dstTexture = t.device.createTexture({
+ size: {
+ width: kDefaultWidth,
+ height: kDefaultHeight,
+ depthOrArrayLayers: kDefaultDepth,
+ },
+ format: 'bgra8unorm',
+ mipLevelCount: kDefaultMipLevelCount,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ let success = true;
+ let hasOperationError = false;
+ const dstMipMapSize = computeMipMapSize(kDefaultWidth, kDefaultHeight, mipLevel);
+
+ if (
+ copySize.depthOrArrayLayers > 1 ||
+ dstOrigin.x + copySize.width > dstMipMapSize.mipWidth ||
+ dstOrigin.y + copySize.height > dstMipMapSize.mipHeight ||
+ dstOrigin.z + copySize.depthOrArrayLayers > kDefaultDepth
+ ) {
+ success = false;
+ }
+ if (copySize.depthOrArrayLayers > 1) {
+ hasOperationError = true;
+ }
+
+ t.runTest(
+ { source: imageBitmap },
+ {
+ texture: dstTexture,
+ mipLevel,
+ origin: dstOrigin,
+ },
+ copySize,
+ success,
+ hasOperationError ? 'OperationError' : ''
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js
new file mode 100644
index 0000000000..e1fcb161bc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/destroyed/query_set.spec.js
@@ -0,0 +1,64 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests using a destroyed query set on a queue.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('beginOcclusionQuery')
+ .desc(
+ `
+Tests that use a destroyed query set in occlusion query on render pass encoder.
+- x= {destroyed, not destroyed (control case)}
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('querySetState', ['valid', 'destroyed']))
+ .fn(t => {
+ const occlusionQuerySet = t.createQuerySetWithState(t.params.querySetState);
+
+ const encoder = t.createEncoder('render pass', { occlusionQuerySet });
+ encoder.encoder.beginOcclusionQuery(0);
+ encoder.encoder.endOcclusionQuery();
+ encoder.validateFinishAndSubmitGivenState(t.params.querySetState);
+ });
+
+g.test('writeTimestamp')
+ .desc(
+ `
+Tests that use a destroyed query set in writeTimestamp on {non-pass, compute, render} encoder.
+- x= {destroyed, not destroyed (control case)}
+ `
+ )
+ .params(u => u.beginSubcases().combine('querySetState', ['valid', 'destroyed']))
+ .beforeAllSubcases(t => t.selectDeviceOrSkipTestCase('timestamp-query'))
+ .fn(async t => {
+ const querySet = t.createQuerySetWithState(t.params.querySetState, {
+ type: 'timestamp',
+ count: 2,
+ });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.writeTimestamp(querySet, 0);
+ encoder.validateFinishAndSubmitGivenState(t.params.querySetState);
+ });
+
+g.test('resolveQuerySet')
+ .desc(
+ `
+Tests that use a destroyed query set in resolveQuerySet.
+- x= {destroyed, not destroyed (control case)}
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('querySetState', ['valid', 'destroyed']))
+ .fn(async t => {
+ const querySet = t.createQuerySetWithState(t.params.querySetState);
+
+ const buffer = t.device.createBuffer({ size: 8, usage: GPUBufferUsage.QUERY_RESOLVE });
+
+ const encoder = t.createEncoder('non-pass');
+ encoder.encoder.resolveQuerySet(querySet, 0, 1, buffer, 0);
+ encoder.validateFinishAndSubmitGivenState(t.params.querySetState);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/submit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/submit.spec.js
new file mode 100644
index 0000000000..588da29d54
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/submit.spec.js
@@ -0,0 +1,48 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests submit validation.
+
+Note: destroyed buffer/texture/querySet are tested in destroyed/. (unless it gets moved here)
+Note: buffer map state is tested in ./buffer_mapped.spec.ts.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('command_buffer,device_mismatch')
+ .desc(
+ `
+ Tests submit cannot be called with command buffers created from another device
+ Test with two command buffers to make sure all command buffers can be validated:
+ - cb0 and cb1 from same device
+ - cb0 and cb1 from different device
+ `
+ )
+ .paramsSubcasesOnly([
+ { cb0Mismatched: false, cb1Mismatched: false }, // control case
+ { cb0Mismatched: true, cb1Mismatched: false },
+ { cb0Mismatched: false, cb1Mismatched: true },
+ ])
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { cb0Mismatched, cb1Mismatched } = t.params;
+ const mismatched = cb0Mismatched || cb1Mismatched;
+
+ const encoder0 = cb0Mismatched
+ ? t.mismatchedDevice.createCommandEncoder()
+ : t.device.createCommandEncoder();
+ const cb0 = encoder0.finish();
+
+ const encoder1 = cb1Mismatched
+ ? t.mismatchedDevice.createCommandEncoder()
+ : t.device.createCommandEncoder();
+ const cb1 = encoder1.finish();
+
+ t.expectValidationError(() => {
+ t.device.queue.submit([cb0, cb1]);
+ }, mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeBuffer.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeBuffer.spec.js
new file mode 100644
index 0000000000..1873544ed5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeBuffer.spec.js
@@ -0,0 +1,189 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests writeBuffer validation.
+
+Note: buffer map state is tested in ./buffer_mapped.spec.ts.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kTypedArrayBufferViewConstructors } from '../../../../common/util/util.js';
+import { Float16Array } from '../../../../external/petamoriken/float16/float16.js';
+import { GPUConst } from '../../../constants.js';
+import { kResourceStates } from '../../../gpu_test.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('buffer_state')
+ .desc(
+ `
+ Test that the buffer used for GPUQueue.writeBuffer() must be valid. Tests calling writeBuffer
+ with {valid, invalid, destroyed} buffer.
+ `
+ )
+ .params(u => u.combine('bufferState', kResourceStates))
+ .fn(async t => {
+ const { bufferState } = t.params;
+ const buffer = t.createBufferWithState(bufferState, {
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ const data = new Uint8Array(16);
+ const _valid = bufferState === 'valid';
+
+ t.expectValidationError(() => {
+ t.device.queue.writeBuffer(buffer, 0, data, 0, data.length);
+ }, !_valid);
+ });
+
+g.test('ranges')
+ .desc(
+ `
+ Tests that the data ranges given to GPUQueue.writeBuffer() are properly validated. Tests calling
+ writeBuffer with both TypedArrays and ArrayBuffers and checks that the data offset and size is
+ interpreted correctly for both.
+ - When passing a TypedArray the data offset and size is given in elements.
+ - When passing an ArrayBuffer the data offset and size is given in bytes.
+
+ Also verifies that the specified data range:
+ - Describes a valid range of the destination buffer and source buffer.
+ - Fits fully within the destination buffer.
+ - Has a byte size which is a multiple of 4.
+ `
+ )
+ .fn(async t => {
+ const queue = t.device.queue;
+
+ function runTest(arrayType, testBuffer) {
+ const elementSize = arrayType.BYTES_PER_ELEMENT;
+ const bufferSize = 16 * elementSize;
+ const buffer = t.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ const arraySm = testBuffer ? new arrayType(8).buffer : new arrayType(8);
+ const arrayMd = testBuffer ? new arrayType(16).buffer : new arrayType(16);
+ const arrayLg = testBuffer ? new arrayType(32).buffer : new arrayType(32);
+
+ if (elementSize < 4) {
+ const array15 = testBuffer ? new arrayType(15).buffer : new arrayType(15);
+
+ // Writing the full buffer that isn't 4-byte aligned.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, array15));
+
+ // Writing from an offset that causes source to be 4-byte aligned.
+ queue.writeBuffer(buffer, 0, array15, 3);
+
+ // Writing from an offset that causes the source to not be 4-byte aligned.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arrayMd, 3));
+
+ // Writing with a size that is not 4-byte aligned.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, 0, 7));
+ }
+
+ // Writing the full buffer without offsets.
+ queue.writeBuffer(buffer, 0, arraySm);
+ queue.writeBuffer(buffer, 0, arrayMd);
+ t.expectValidationError(() => queue.writeBuffer(buffer, 0, arrayLg));
+
+ // Writing the full buffer with a 4-byte aligned offset.
+ queue.writeBuffer(buffer, 8, arraySm);
+ t.expectValidationError(() => queue.writeBuffer(buffer, 8, arrayMd));
+
+ // Writing the full buffer with a unaligned offset.
+ t.expectValidationError(() => queue.writeBuffer(buffer, 3, arraySm));
+
+ // Writing remainder of buffer from offset.
+ queue.writeBuffer(buffer, 0, arraySm, 4);
+ queue.writeBuffer(buffer, 0, arrayMd, 4);
+ t.expectValidationError(() => queue.writeBuffer(buffer, 0, arrayLg, 4));
+
+ // Writing a larger buffer from an offset that allows it to fit in the destination.
+ queue.writeBuffer(buffer, 0, arrayLg, 16);
+
+ // Writing with both an offset and size.
+ queue.writeBuffer(buffer, 0, arraySm, 4, 4);
+
+ // Writing with a size that extends past the source buffer length.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, 0, 16));
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, 4, 8));
+
+ // Writing with a size that is 4-byte aligned but an offset that is not.
+ queue.writeBuffer(buffer, 0, arraySm, 3, 4);
+
+ // Writing zero bytes at the end of the buffer.
+ queue.writeBuffer(buffer, bufferSize, arraySm, 0, 0);
+
+ // Writing with a buffer offset that is out of range of buffer size.
+ t.expectValidationError(() => queue.writeBuffer(buffer, bufferSize + 4, arraySm, 0, 0));
+
+ // Writing zero bytes from the end of the data.
+ queue.writeBuffer(buffer, 0, arraySm, 8, 0);
+
+ // Writing with a data offset that is out of range of data size.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, 9, 0));
+
+ // Writing with a data offset that is out of range of data size with implicit copy size.
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, 9, undefined));
+
+ // A data offset of undefined should be treated as 0.
+ queue.writeBuffer(buffer, 0, arraySm, undefined, 8);
+ t.shouldThrow('OperationError', () => queue.writeBuffer(buffer, 0, arraySm, undefined, 12));
+ }
+
+ runTest(Uint8Array, true);
+
+ for (const arrayType of kTypedArrayBufferViewConstructors) {
+ if (arrayType === Float16Array) {
+ // Skip Float16Array since it is supplied by an external module, so there isn't an overload for it.
+ continue;
+ }
+ runTest(arrayType, false);
+ }
+ });
+
+g.test('usages')
+ .desc(
+ `
+ Tests calling writeBuffer with the buffer missed COPY_DST usage.
+ - buffer {with, without} COPY DST usage
+ `
+ )
+ .paramsSubcasesOnly([
+ { usage: GPUConst.BufferUsage.COPY_DST, _valid: true }, // control case
+ { usage: GPUConst.BufferUsage.STORAGE, _valid: false }, // without COPY_DST usage
+ { usage: GPUConst.BufferUsage.STORAGE | GPUConst.BufferUsage.COPY_SRC, _valid: false }, // with other usage
+ { usage: GPUConst.BufferUsage.STORAGE | GPUConst.BufferUsage.COPY_DST, _valid: true }, // with COPY_DST usage
+ ])
+ .fn(async t => {
+ const { usage, _valid } = t.params;
+ const buffer = t.device.createBuffer({ size: 16, usage });
+ const data = new Uint8Array(16);
+
+ t.expectValidationError(() => {
+ t.device.queue.writeBuffer(buffer, 0, data, 0, data.length);
+ }, !_valid);
+ });
+
+g.test('buffer,device_mismatch')
+ .desc('Tests writeBuffer cannot be called with a buffer created from another device.')
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const buffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ const data = new Uint8Array(16);
+
+ t.expectValidationError(() => {
+ t.device.queue.writeBuffer(buffer, 0, data, 0, data.length);
+ }, mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeTexture.spec.js
new file mode 100644
index 0000000000..cab0200fc2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/queue/writeTexture.spec.js
@@ -0,0 +1,111 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Tests writeTexture validation.`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../constants.js';
+import { kResourceStates } from '../../../gpu_test.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('texture_state')
+ .desc(
+ `
+ Test that the texture used for GPUQueue.writeTexture() must be valid. Tests calling writeTexture
+ with {valid, invalid, destroyed} texture.
+ `
+ )
+ .params(u => u.combine('textureState', kResourceStates))
+ .fn(async t => {
+ const { textureState } = t.params;
+ const texture = t.createTextureWithState(textureState);
+ const data = new Uint8Array(16);
+ const size = [1, 1];
+
+ const isValid = textureState === 'valid';
+
+ t.expectValidationError(() => {
+ t.device.queue.writeTexture({ texture }, data, {}, size);
+ }, !isValid);
+ });
+
+g.test('usages')
+ .desc(
+ `
+ Tests calling writeTexture with the texture missed COPY_DST usage.
+ - texture {with, without} COPY DST usage
+ `
+ )
+ .paramsSubcasesOnly([
+ { usage: GPUConst.TextureUsage.COPY_DST }, // control case
+ { usage: GPUConst.TextureUsage.STORAGE_BINDING },
+ { usage: GPUConst.TextureUsage.STORAGE_BINDING | GPUConst.TextureUsage.COPY_SRC },
+ { usage: GPUConst.TextureUsage.STORAGE_BINDING | GPUConst.TextureUsage.COPY_DST },
+ ])
+ .fn(async t => {
+ const { usage } = t.params;
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16 },
+ usage,
+ format: 'rgba8unorm',
+ });
+ const data = new Uint8Array(16);
+ const size = [1, 1];
+
+ const isValid = usage & GPUConst.TextureUsage.COPY_DST ? true : false;
+ t.expectValidationError(() => {
+ t.device.queue.writeTexture({ texture }, data, {}, size);
+ }, !isValid);
+ });
+
+g.test('sample_count')
+ .desc(
+ `
+ Test that the texture sample count. Check that a validation error is generated if sample count is
+ not 1.
+ `
+ )
+ .params(u => u.combine('sampleCount', [1, 4]))
+ .fn(async t => {
+ const { sampleCount } = t.params;
+ const texture = t.device.createTexture({
+ size: { width: 16, height: 16 },
+ sampleCount,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const data = new Uint8Array(16);
+ const size = [1, 1];
+
+ const isValid = sampleCount === 1;
+
+ t.expectValidationError(() => {
+ t.device.queue.writeTexture({ texture }, data, {}, size);
+ }, !isValid);
+ });
+
+g.test('texture,device_mismatch')
+ .desc('Tests writeTexture cannot be called with a texture created from another device.')
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const texture = sourceDevice.createTexture({
+ size: { width: 16, height: 16 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ t.trackForCleanup(texture);
+
+ const data = new Uint8Array(16);
+ const size = [1, 1];
+
+ t.expectValidationError(() => {
+ t.device.queue.writeTexture({ texture }, data, {}, size);
+ }, mismatched);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js
new file mode 100644
index 0000000000..02563030ba
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/attachment_compatibility.spec.js
@@ -0,0 +1,631 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation for attachment compatibility between render passes, bundles, and pipelines
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import {
+ kRegularTextureFormats,
+ kSizedDepthStencilFormats,
+ kUnsizedDepthStencilFormats,
+ kTextureSampleCounts,
+ kMaxColorAttachments,
+ kTextureFormatInfo,
+ getFeaturesForFormats,
+ filterFormatsByFeature,
+} from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+const kColorAttachmentCounts = range(kMaxColorAttachments, i => i + 1);
+const kColorAttachments = kColorAttachmentCounts
+ .map(count => {
+ // generate cases with 0..1 null attachments at different location
+ // e.g. count == 2
+ // [
+ // [1, 1],
+ // [0, 1],
+ // [1, 0],
+ // ]
+ // 0 (false) means null attachment, 1 (true) means non-null attachment, at the slot
+
+ // Special cases: we need at least a color attachment, when we don't have depth stencil attachment
+ if (count === 1) {
+ return [[1]];
+ }
+ if (count === 2) {
+ return [
+ [1, 1],
+ [0, 1],
+ [1, 0],
+ ];
+ }
+
+ // [1, 1, ..., 1]: all color attachment are used
+ let result = [new Array(count).fill(true)];
+
+ // [1, 0, 1, ..., 1]: generate cases with one null attachment at different locations
+ result = result.concat(
+ range(count, i => {
+ const r = new Array(count).fill(true);
+ r[i] = false;
+ return r;
+ })
+ );
+
+ // [1, 0, 1, ..., 0, 1]: generate cases with two null attachments at different locations
+ // To reduce test run time, limit the attachment count to <= 4
+ if (count <= 4) {
+ result = result.concat(
+ range(count - 1, i => {
+ const cases = [];
+ for (let j = i + 1; j < count; j++) {
+ const r = new Array(count).fill(true);
+ r[i] = false;
+ r[j] = false;
+ cases.push(r);
+ }
+ return cases;
+ }).flat()
+ );
+ }
+
+ return result;
+ })
+ .flat();
+
+const kDepthStencilAttachmentFormats = [
+ undefined,
+ ...kSizedDepthStencilFormats,
+ ...kUnsizedDepthStencilFormats,
+];
+
+const kFeaturesForDepthStencilAttachmentFormats = getFeaturesForFormats([
+ ...kSizedDepthStencilFormats,
+ ...kUnsizedDepthStencilFormats,
+]);
+
+class F extends ValidationTest {
+ createAttachmentTextureView(format, sampleCount) {
+ return this.device
+ .createTexture({
+ // Size matching the "arbitrary" size used by ValidationTest helpers.
+ size: [16, 16, 1],
+ format,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount,
+ })
+ .createView();
+ }
+
+ createColorAttachment(format, sampleCount) {
+ return format === null
+ ? null
+ : {
+ view: this.createAttachmentTextureView(format, sampleCount),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ };
+ }
+
+ createDepthAttachment(format, sampleCount) {
+ const attachment = {
+ view: this.createAttachmentTextureView(format, sampleCount),
+ };
+ if (kTextureFormatInfo[format].depth) {
+ attachment.depthClearValue = 0;
+ attachment.depthLoadOp = 'clear';
+ attachment.depthStoreOp = 'discard';
+ }
+ if (kTextureFormatInfo[format].stencil) {
+ attachment.stencilClearValue = 1;
+ attachment.stencilLoadOp = 'clear';
+ attachment.stencilStoreOp = 'discard';
+ }
+ return attachment;
+ }
+
+ createRenderPipeline(targets, depthStencil, sampleCount, cullMode) {
+ return this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 0.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: '@fragment fn main() {}',
+ }),
+ entryPoint: 'main',
+ targets,
+ },
+ primitive: { topology: 'triangle-list', cullMode },
+ depthStencil,
+ multisample: { count: sampleCount },
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kColorAttachmentFormats = kRegularTextureFormats.filter(format => {
+ const info = kTextureFormatInfo[format];
+ return info.color && info.renderable;
+});
+
+g.test('render_pass_and_bundle,color_format')
+ .desc('Test that color attachment formats in render passes and bundles must match.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('passFormat', kColorAttachmentFormats)
+ .combine('bundleFormat', kColorAttachmentFormats)
+ )
+ .fn(t => {
+ const { passFormat, bundleFormat } = t.params;
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: [bundleFormat],
+ });
+ const bundle = bundleEncoder.finish();
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [t.createColorAttachment(passFormat)],
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(passFormat === bundleFormat, true);
+ });
+
+g.test('render_pass_and_bundle,color_count')
+ .desc(
+ `
+ Test that the number of color attachments in render passes and bundles must match.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('passCount', kColorAttachmentCounts)
+ .combine('bundleCount', kColorAttachmentCounts)
+ )
+ .fn(t => {
+ const { passCount, bundleCount } = t.params;
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: range(bundleCount, () => 'rgba8uint'),
+ });
+ const bundle = bundleEncoder.finish();
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: range(passCount, () => t.createColorAttachment('rgba8uint')),
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(passCount === bundleCount, true);
+ });
+
+g.test('render_pass_and_bundle,color_sparse')
+ .desc(
+ `
+ Test that each of color attachments in render passes and bundles must match.
+ `
+ )
+ .params(u =>
+ u //
+ // introduce attachmentCount to make it easier to split the test
+ .combine('attachmentCount', kColorAttachmentCounts)
+ .beginSubcases()
+ .combine('passAttachments', kColorAttachments)
+ .combine('bundleAttachments', kColorAttachments)
+ .filter(
+ p =>
+ p.attachmentCount === p.passAttachments.length &&
+ p.attachmentCount === p.bundleAttachments.length
+ )
+ )
+ .fn(t => {
+ const { passAttachments, bundleAttachments } = t.params;
+ const colorFormats = bundleAttachments.map(i => (i ? 'rgba8uint' : null));
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const colorAttachments = passAttachments.map(i =>
+ t.createColorAttachment(i ? 'rgba8uint' : null)
+ );
+
+ const pass = encoder.beginRenderPass({
+ colorAttachments,
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(
+ passAttachments.every((v, i) => v === bundleAttachments[i]),
+ true
+ );
+ });
+
+g.test('render_pass_and_bundle,depth_format')
+ .desc('Test that the depth attachment format in render passes and bundles must match.')
+ .params(u =>
+ u //
+ .combine('passFeature', kFeaturesForDepthStencilAttachmentFormats)
+ .combine('bundleFeature', kFeaturesForDepthStencilAttachmentFormats)
+ .beginSubcases()
+ .expand('passFormat', ({ passFeature }) =>
+ filterFormatsByFeature(passFeature, kDepthStencilAttachmentFormats)
+ )
+ .expand('bundleFormat', ({ bundleFeature }) =>
+ filterFormatsByFeature(bundleFeature, kDepthStencilAttachmentFormats)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { passFeature, bundleFeature } = t.params;
+ t.selectDeviceOrSkipTestCase([passFeature, bundleFeature]);
+ })
+ .fn(async t => {
+ const { passFormat, bundleFormat } = t.params;
+
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ depthStencilFormat: bundleFormat,
+ });
+ const bundle = bundleEncoder.finish();
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [t.createColorAttachment('rgba8unorm')],
+ depthStencilAttachment:
+ passFormat !== undefined ? t.createDepthAttachment(passFormat) : undefined,
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(passFormat === bundleFormat, true);
+ });
+
+g.test('render_pass_and_bundle,sample_count')
+ .desc('Test that the sample count in render passes and bundles must match.')
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('renderSampleCount', kTextureSampleCounts)
+ .combine('bundleSampleCount', kTextureSampleCounts)
+ )
+ .fn(t => {
+ const { renderSampleCount, bundleSampleCount } = t.params;
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ sampleCount: bundleSampleCount,
+ });
+ const bundle = bundleEncoder.finish();
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [t.createColorAttachment('rgba8unorm', renderSampleCount)],
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(renderSampleCount === bundleSampleCount, true);
+ });
+
+g.test('render_pass_and_bundle,device_mismatch')
+ .desc('Test that render passes cannot be called with bundles created from another device.')
+ .paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(t => {
+ const { mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const format = 'r16float';
+ const bundleEncoder = sourceDevice.createRenderBundleEncoder({
+ colorFormats: [format],
+ });
+ const bundle = bundleEncoder.finish();
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder('non-pass');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [t.createColorAttachment(format)],
+ });
+ pass.executeBundles([bundle]);
+ pass.end();
+ validateFinishAndSubmit(!mismatched, true);
+ });
+
+g.test('render_pass_or_bundle_and_pipeline,color_format')
+ .desc(
+ `
+Test that color attachment formats in render passes or bundles match the pipeline color format.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ .beginSubcases()
+ .combine('encoderFormat', kColorAttachmentFormats)
+ .combine('pipelineFormat', kColorAttachmentFormats)
+ )
+ .fn(t => {
+ const { encoderType, encoderFormat, pipelineFormat } = t.params;
+ const pipeline = t.createRenderPipeline([{ format: pipelineFormat, writeMask: 0 }]);
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: { colorFormats: [encoderFormat] },
+ });
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmit(encoderFormat === pipelineFormat, true);
+ });
+
+g.test('render_pass_or_bundle_and_pipeline,color_count')
+ .desc(
+ `
+Test that the number of color attachments in render passes or bundles match the pipeline color
+count.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ .beginSubcases()
+ .combine('encoderCount', kColorAttachmentCounts)
+ .combine('pipelineCount', kColorAttachmentCounts)
+ )
+ .fn(t => {
+ const { encoderType, encoderCount, pipelineCount } = t.params;
+ const pipeline = t.createRenderPipeline(
+ range(pipelineCount, () => ({ format: 'rgba8uint', writeMask: 0 }))
+ );
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: { colorFormats: range(encoderCount, () => 'rgba8uint') },
+ });
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmit(encoderCount === pipelineCount, true);
+ });
+
+g.test('render_pass_or_bundle_and_pipeline,color_sparse')
+ .desc(
+ `
+Test that each of color attachments in render passes or bundles match that of the pipeline.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ // introduce attachmentCount to make it easier to split the test
+ .combine('attachmentCount', kColorAttachmentCounts)
+ .beginSubcases()
+ .combine('encoderAttachments', kColorAttachments)
+ .combine('pipelineAttachments', kColorAttachments)
+ .filter(
+ p =>
+ p.attachmentCount === p.encoderAttachments.length &&
+ p.attachmentCount === p.pipelineAttachments.length
+ )
+ )
+ .fn(t => {
+ const { encoderType, encoderAttachments, pipelineAttachments } = t.params;
+
+ const colorTargets = pipelineAttachments.map(i =>
+ i ? { format: 'rgba8uint', writeMask: 0 } : null
+ );
+
+ const pipeline = t.createRenderPipeline(colorTargets);
+
+ const colorFormats = encoderAttachments.map(i => (i ? 'rgba8uint' : null));
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: { colorFormats },
+ });
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmit(
+ encoderAttachments.every((v, i) => v === pipelineAttachments[i]),
+ true
+ );
+ });
+
+g.test('render_pass_or_bundle_and_pipeline,depth_format')
+ .desc(
+ `
+Test that the depth attachment format in render passes or bundles match the pipeline depth format.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ .combine('encoderFormatFeature', kFeaturesForDepthStencilAttachmentFormats)
+ .combine('pipelineFormatFeature', kFeaturesForDepthStencilAttachmentFormats)
+ .beginSubcases()
+ .expand('encoderFormat', ({ encoderFormatFeature }) =>
+ filterFormatsByFeature(encoderFormatFeature, kDepthStencilAttachmentFormats)
+ )
+ .expand('pipelineFormat', ({ pipelineFormatFeature }) =>
+ filterFormatsByFeature(pipelineFormatFeature, kDepthStencilAttachmentFormats)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { encoderFormatFeature, pipelineFormatFeature } = t.params;
+ t.selectDeviceOrSkipTestCase([encoderFormatFeature, pipelineFormatFeature]);
+ })
+ .fn(async t => {
+ const { encoderType, encoderFormat, pipelineFormat } = t.params;
+
+ const pipeline = t.createRenderPipeline(
+ [{ format: 'rgba8unorm', writeMask: 0 }],
+ pipelineFormat !== undefined ? { format: pipelineFormat } : undefined
+ );
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: { colorFormats: ['rgba8unorm'], depthStencilFormat: encoderFormat },
+ });
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmit(encoderFormat === pipelineFormat, true);
+ });
+
+const kStencilFaceStates = [
+ { failOp: 'keep', depthFailOp: 'keep', passOp: 'keep' },
+ { failOp: 'zero', depthFailOp: 'zero', passOp: 'zero' },
+];
+
+g.test('render_pass_or_bundle_and_pipeline,depth_stencil_read_only_write_state')
+ .desc(
+ `
+Test that the depth stencil read only state in render passes or bundles is compatible with the depth stencil write state of the pipeline.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ .combine('format', kDepthStencilAttachmentFormats)
+ .beginSubcases()
+ // pass/bundle state
+ .combine('depthReadOnly', [false, true])
+ .combine('stencilReadOnly', [false, true])
+ .combine('stencilFront', kStencilFaceStates)
+ .combine('stencilBack', kStencilFaceStates)
+ // pipeline state
+ .combine('depthWriteEnabled', [false, true])
+ .combine('stencilWriteMask', [0, 0xffffffff])
+ .combine('cullMode', ['none', 'front', 'back'])
+ .filter(p => {
+ if (p.format) {
+ const depthStencilInfo = kTextureFormatInfo[p.format];
+ // For combined depth/stencil formats the depth and stencil read only state must match
+ // in order to create a valid render bundle or render pass.
+ if (depthStencilInfo.depth && depthStencilInfo.stencil) {
+ if (p.depthReadOnly !== p.stencilReadOnly) {
+ return false;
+ }
+ }
+ // If the format has no depth aspect, the depthReadOnly, depthWriteEnabled of the pipeline must not be true
+ // in order to create a valid render pipeline.
+ if (!depthStencilInfo.depth && p.depthWriteEnabled) {
+ return false;
+ }
+ // If the format has no stencil aspect, the stencil state operation must be 'keep'
+ // in order to create a valid render pipeline.
+ if (
+ !depthStencilInfo.stencil &&
+ (p.stencilFront.failOp !== 'keep' || p.stencilBack.failOp !== 'keep')
+ ) {
+ return false;
+ }
+ }
+ // No depthStencil attachment
+ return true;
+ })
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const {
+ encoderType,
+ format,
+ depthReadOnly,
+ stencilReadOnly,
+ depthWriteEnabled,
+ stencilWriteMask,
+ cullMode,
+ stencilFront,
+ stencilBack,
+ } = t.params;
+
+ const pipeline = t.createRenderPipeline(
+ [{ format: 'rgba8unorm', writeMask: 0 }],
+ format === undefined
+ ? undefined
+ : {
+ format,
+ depthWriteEnabled,
+ stencilWriteMask,
+ stencilFront,
+ stencilBack,
+ },
+ 1,
+ cullMode
+ );
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: {
+ colorFormats: ['rgba8unorm'],
+ depthStencilFormat: format,
+ depthReadOnly,
+ stencilReadOnly,
+ },
+ });
+ encoder.setPipeline(pipeline);
+
+ let writesDepth = false;
+ let writesStencil = false;
+ if (format) {
+ writesDepth = depthWriteEnabled;
+ if (stencilWriteMask !== 0) {
+ if (
+ cullMode !== 'front' &&
+ (stencilFront.passOp !== 'keep' ||
+ stencilFront.depthFailOp !== 'keep' ||
+ stencilFront.failOp !== 'keep')
+ ) {
+ writesStencil = true;
+ }
+ if (
+ cullMode !== 'back' &&
+ (stencilBack.passOp !== 'keep' ||
+ stencilBack.depthFailOp !== 'keep' ||
+ stencilBack.failOp !== 'keep')
+ ) {
+ writesStencil = true;
+ }
+ }
+ }
+
+ let isValid = true;
+ if (writesDepth) {
+ isValid &&= !depthReadOnly;
+ }
+ if (writesStencil) {
+ isValid &&= !stencilReadOnly;
+ }
+
+ validateFinishAndSubmit(isValid, true);
+ });
+
+g.test('render_pass_or_bundle_and_pipeline,sample_count')
+ .desc(
+ `
+Test that the sample count in render passes or bundles match the pipeline sample count for both color texture and depthstencil texture.
+`
+ )
+ .params(u =>
+ u
+ .combine('encoderType', ['render pass', 'render bundle'])
+ .combine('attachmentType', ['color', 'depthstencil'])
+ .beginSubcases()
+ .combine('encoderSampleCount', kTextureSampleCounts)
+ .combine('pipelineSampleCount', kTextureSampleCounts)
+ )
+ .fn(t => {
+ const { encoderType, attachmentType, encoderSampleCount, pipelineSampleCount } = t.params;
+
+ const colorFormats = attachmentType === 'color' ? ['rgba8unorm'] : [];
+ const depthStencilFormat =
+ attachmentType === 'depthstencil' ? 'depth24plus-stencil8' : undefined;
+
+ const pipeline = t.createRenderPipeline(
+ colorFormats.map(format => ({ format, writeMask: 0 })),
+ depthStencilFormat ? { format: depthStencilFormat } : undefined,
+ pipelineSampleCount
+ );
+
+ const { encoder, validateFinishAndSubmit } = t.createEncoder(encoderType, {
+ attachmentInfo: { colorFormats, depthStencilFormat, sampleCount: encoderSampleCount },
+ });
+ encoder.setPipeline(pipeline);
+ validateFinishAndSubmit(encoderSampleCount === pipelineSampleCount, true);
+ });
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
new file mode 100644
index 0000000000..f3867ed1ec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/render_pass_descriptor.spec.js
@@ -0,0 +1,1106 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+render pass descriptor validation tests.
+
+TODO: review for completeness
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import {
+ kDepthStencilFormats,
+ kMaxColorAttachments,
+ kQueryTypes,
+ kRenderableColorTextureFormats,
+ kTextureFormatInfo,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { ValidationTest } from '../validation_test.js';
+
+class F extends ValidationTest {
+ createTexture(options = {}) {
+ const {
+ format = 'rgba8unorm',
+ width = 16,
+ height = 16,
+ arrayLayerCount = 1,
+ mipLevelCount = 1,
+ sampleCount = 1,
+ usage = GPUTextureUsage.RENDER_ATTACHMENT,
+ } = options;
+
+ return this.device.createTexture({
+ size: { width, height, depthOrArrayLayers: arrayLayerCount },
+ format,
+ mipLevelCount,
+ sampleCount,
+ usage,
+ });
+ }
+
+ getColorAttachment(texture, textureViewDescriptor) {
+ const view = texture.createView(textureViewDescriptor);
+
+ return {
+ view,
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ };
+ }
+
+ getDepthStencilAttachment(texture, textureViewDescriptor) {
+ const view = texture.createView(textureViewDescriptor);
+
+ return {
+ view,
+ depthClearValue: 1.0,
+ depthLoadOp: 'clear',
+ depthStoreOp: 'store',
+ stencilClearValue: 0,
+ stencilLoadOp: 'clear',
+ stencilStoreOp: 'store',
+ };
+ }
+
+ tryRenderPass(success, descriptor) {
+ const commandEncoder = this.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass(descriptor);
+ renderPass.end();
+
+ this.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !success);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('attachments,one_color_attachment')
+ .desc(`Test that a render pass works with only one color attachment.`)
+ .fn(t => {
+ const colorTexture = t.createTexture({ format: 'rgba8unorm' });
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ };
+
+ t.tryRenderPass(true, descriptor);
+ });
+
+g.test('attachments,one_depth_stencil_attachment')
+ .desc(`Test that a render pass works with only one depthStencil attachment.`)
+ .fn(t => {
+ const depthStencilTexture = t.createTexture({ format: 'depth24plus-stencil8' });
+ const descriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture),
+ };
+
+ t.tryRenderPass(true, descriptor);
+ });
+
+g.test('color_attachments,empty')
+ .desc(
+ `
+ Test that when colorAttachments has all values be 'undefined' or the sequence is empty, the
+ depthStencilAttachment must not be 'undefined'.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('colorAttachments', [
+ [],
+ [undefined],
+ [undefined, undefined],
+ new Array(8).fill(undefined),
+ [{ format: 'rgba8unorm' }],
+ ])
+ .combine('hasDepthStencilAttachment', [false, true])
+ )
+ .fn(async t => {
+ const { colorAttachments, hasDepthStencilAttachment } = t.params;
+
+ let isEmptyColorTargets = true;
+ for (let i = 0; i < colorAttachments.length; i++) {
+ if (colorAttachments[i] !== undefined) {
+ isEmptyColorTargets = false;
+ const colorTexture = t.createTexture();
+ colorAttachments[i] = t.getColorAttachment(colorTexture);
+ }
+ }
+
+ const _success = !isEmptyColorTargets || hasDepthStencilAttachment;
+ t.tryRenderPass(_success, {
+ colorAttachments,
+ depthStencilAttachment: hasDepthStencilAttachment
+ ? t.getDepthStencilAttachment(t.createTexture({ format: 'depth24plus-stencil8' }))
+ : undefined,
+ });
+ });
+
+g.test('color_attachments,limits,maxColorAttachments')
+ .desc(
+ `
+ Test that the out of bound of color attachment indexes are handled.
+ - a validation error is generated when color attachments exceed the maximum limit(8).
+ `
+ )
+ .paramsSimple([
+ { colorAttachmentsCount: 8, _success: true }, // Control case
+ { colorAttachmentsCount: 9, _success: false }, // Out of bounds
+ ])
+ .fn(async t => {
+ const { colorAttachmentsCount, _success } = t.params;
+
+ const colorAttachments = [];
+ for (let i = 0; i < colorAttachmentsCount; i++) {
+ const colorTexture = t.createTexture();
+ colorAttachments.push(t.getColorAttachment(colorTexture));
+ }
+
+ t.tryRenderPass(_success, { colorAttachments });
+ });
+
+g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,aligned')
+ .desc(
+ `
+ Test that the total bytes per sample of the formats of the color attachments must be no greater
+ than maxColorAttachmentBytesPerSample when the components are aligned (same format).
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine(
+ 'attachmentCount',
+ range(kMaxColorAttachments, i => i + 1)
+ )
+ )
+ .fn(async t => {
+ const { format, attachmentCount } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const colorAttachments = [];
+ for (let i = 0; i < attachmentCount; i++) {
+ const colorTexture = t.createTexture();
+ colorAttachments.push(t.getColorAttachment(colorTexture));
+ }
+ const shouldError =
+ info.renderTargetPixelByteCost === undefined ||
+ info.renderTargetPixelByteCost * attachmentCount >
+ t.device.limits.maxColorAttachmentBytesPerSample;
+
+ t.tryRenderPass(!shouldError, { colorAttachments });
+ });
+
+g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned')
+ .desc(
+ `
+ Test that the total bytes per sample of the formats of the color attachments must be no greater
+ than maxColorAttachmentBytesPerSample when the components are (potentially) unaligned.
+ `
+ )
+ .params(u =>
+ u.combineWithParams([
+ // Alignment causes the first 1 byte R8Unorm to become 4 bytes. So even though
+ // 1+4+8+16+1 < 32, the 4 byte alignment requirement of R32Float makes the first R8Unorm
+ // become 4 and 4+4+8+16+1 > 32. Re-ordering this so the R8Unorm's are at the end, however
+ // is allowed: 4+8+16+1+1 < 32.
+ {
+ formats: ['r8unorm', 'r32float', 'rgba8unorm', 'rgba32float', 'r8unorm'],
+
+ _success: true,
+ },
+ {
+ formats: ['r32float', 'rgba8unorm', 'rgba32float', 'r8unorm', 'r8unorm'],
+
+ _success: false,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { formats, _success } = t.params;
+
+ const colorAttachments = [];
+ for (const format of formats) {
+ const colorTexture = t.createTexture({ format });
+ colorAttachments.push(t.getColorAttachment(colorTexture));
+ }
+ t.tryRenderPass(_success, { colorAttachments });
+ });
+
+g.test('attachments,same_size')
+ .desc(
+ `
+ Test that attachments have the same size. Otherwise, a validation error should be generated.
+ - Succeed if all attachments have the same size.
+ - Fail if one of the color attachments has a different size.
+ - Fail if the depth stencil attachment has a different size.
+ `
+ )
+ .fn(async t => {
+ const colorTexture1x1A = t.createTexture({ width: 1, height: 1, format: 'rgba8unorm' });
+ const colorTexture1x1B = t.createTexture({ width: 1, height: 1, format: 'rgba8unorm' });
+ const colorTexture2x2 = t.createTexture({ width: 2, height: 2, format: 'rgba8unorm' });
+ const depthStencilTexture1x1 = t.createTexture({
+ width: 1,
+ height: 1,
+ format: 'depth24plus-stencil8',
+ });
+ const depthStencilTexture2x2 = t.createTexture({
+ width: 2,
+ height: 2,
+ format: 'depth24plus-stencil8',
+ });
+
+ {
+ // Control case: all the same size (1x1)
+ const descriptor = {
+ colorAttachments: [
+ t.getColorAttachment(colorTexture1x1A),
+ t.getColorAttachment(colorTexture1x1B),
+ ],
+
+ depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture1x1),
+ };
+
+ t.tryRenderPass(true, descriptor);
+ }
+ {
+ // One of the color attachments has a different size
+ const descriptor = {
+ colorAttachments: [
+ t.getColorAttachment(colorTexture1x1A),
+ t.getColorAttachment(colorTexture2x2),
+ ],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ {
+ // The depth stencil attachment has a different size
+ const descriptor = {
+ colorAttachments: [
+ t.getColorAttachment(colorTexture1x1A),
+ t.getColorAttachment(colorTexture1x1B),
+ ],
+
+ depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture2x2),
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ });
+
+g.test('attachments,color_depth_mismatch')
+ .desc(`Test that attachments match whether they are used for color or depth stencil.`)
+ .fn(async t => {
+ const colorTexture = t.createTexture({ format: 'rgba8unorm' });
+ const depthStencilTexture = t.createTexture({ format: 'depth24plus-stencil8' });
+
+ {
+ // Using depth-stencil for color
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(depthStencilTexture)],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ {
+ // Using color for depth-stencil
+ const descriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(colorTexture),
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ });
+
+g.test('attachments,layer_count')
+ .desc(
+ `
+ Test the layer counts for color or depth stencil.
+ - Fail if using 2D array texture view with arrayLayerCount > 1.
+ - Succeed if using 2D array texture view that covers the first layer of the texture.
+ - Succeed if using 2D array texture view that covers the last layer for depth stencil.
+ `
+ )
+ .paramsSimple([
+ { arrayLayerCount: 5, baseArrayLayer: 0, _success: false },
+ { arrayLayerCount: 1, baseArrayLayer: 0, _success: true },
+ { arrayLayerCount: 1, baseArrayLayer: 9, _success: true },
+ ])
+ .fn(async t => {
+ const { arrayLayerCount, baseArrayLayer, _success } = t.params;
+
+ const ARRAY_LAYER_COUNT = 10;
+ const MIP_LEVEL_COUNT = 1;
+ const COLOR_FORMAT = 'rgba8unorm';
+ const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
+
+ const colorTexture = t.createTexture({
+ format: COLOR_FORMAT,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+ const depthStencilTexture = t.createTexture({
+ format: DEPTH_STENCIL_FORMAT,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+
+ const baseTextureViewDescriptor = {
+ dimension: '2d-array',
+ baseArrayLayer,
+ arrayLayerCount,
+ baseMipLevel: 0,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ };
+
+ {
+ // Check 2D array texture view for color
+ const textureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: COLOR_FORMAT,
+ };
+
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
+ };
+
+ t.tryRenderPass(_success, descriptor);
+ }
+ {
+ // Check 2D array texture view for depth stencil
+ const textureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: DEPTH_STENCIL_FORMAT,
+ };
+
+ const descriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(
+ depthStencilTexture,
+ textureViewDescriptor
+ ),
+ };
+
+ t.tryRenderPass(_success, descriptor);
+ }
+ });
+
+g.test('attachments,mip_level_count')
+ .desc(
+ `
+ Test the mip level count for color or depth stencil.
+ - Fail if using 2D texture view with mipLevelCount > 1.
+ - Succeed if using 2D texture view that covers the first level of the texture.
+ - Succeed if using 2D texture view that covers the last level of the texture.
+ `
+ )
+ .paramsSimple([
+ { mipLevelCount: 2, baseMipLevel: 0, _success: false },
+ { mipLevelCount: 1, baseMipLevel: 0, _success: true },
+ { mipLevelCount: 1, baseMipLevel: 3, _success: true },
+ ])
+ .fn(async t => {
+ const { mipLevelCount, baseMipLevel, _success } = t.params;
+
+ const ARRAY_LAYER_COUNT = 1;
+ const MIP_LEVEL_COUNT = 4;
+ const COLOR_FORMAT = 'rgba8unorm';
+ const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
+
+ const colorTexture = t.createTexture({
+ format: COLOR_FORMAT,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+ const depthStencilTexture = t.createTexture({
+ format: DEPTH_STENCIL_FORMAT,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+
+ const baseTextureViewDescriptor = {
+ dimension: '2d',
+ baseArrayLayer: 0,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ baseMipLevel,
+ mipLevelCount,
+ };
+
+ {
+ // Check 2D texture view for color
+ const textureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: COLOR_FORMAT,
+ };
+
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
+ };
+
+ t.tryRenderPass(_success, descriptor);
+ }
+ {
+ // Check 2D texture view for depth stencil
+ const textureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: DEPTH_STENCIL_FORMAT,
+ };
+
+ const descriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(
+ depthStencilTexture,
+ textureViewDescriptor
+ ),
+ };
+
+ t.tryRenderPass(_success, descriptor);
+ }
+ });
+
+g.test('color_attachments,non_multisampled')
+ .desc(
+ `
+ Test that setting a resolve target is invalid if the color attachments is non multisampled.
+ `
+ )
+ .fn(async t => {
+ const colorTexture = t.createTexture({ sampleCount: 1 });
+ const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
+
+ const descriptor = {
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ resolveTarget: resolveTargetTexture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('color_attachments,sample_count')
+ .desc(
+ `
+ Test the usages of multisampled textures for color attachments.
+ - Succeed if using a multisampled color attachment without setting a resolve target.
+ - Fail if using multiple color attachments with different sample counts.
+ `
+ )
+ .fn(async t => {
+ const colorTexture = t.createTexture({ sampleCount: 1 });
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+
+ {
+ // It is allowed to use a multisampled color attachment without setting resolve target
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(multisampledColorTexture)],
+ };
+ t.tryRenderPass(true, descriptor);
+ }
+ {
+ // It is not allowed to use multiple color attachments with different sample counts
+ const descriptor = {
+ colorAttachments: [
+ t.getColorAttachment(colorTexture),
+ t.getColorAttachment(multisampledColorTexture),
+ ],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ });
+
+g.test('resolveTarget,sample_count')
+ .desc(
+ `
+ Test that using multisampled resolve target is invalid for color attachments.
+ `
+ )
+ .fn(async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const multisampledResolveTargetTexture = t.createTexture({ sampleCount: 4 });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = multisampledResolveTargetTexture.createView();
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('resolveTarget,array_layer_count')
+ .desc(
+ `
+ Test that using a resolve target with array layer count is greater than 1 is invalid for color
+ attachments.
+ `
+ )
+ .fn(async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ arrayLayerCount: 2 });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView({ dimension: '2d-array' });
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('resolveTarget,mipmap_level_count')
+ .desc(
+ `
+ Test that using a resolve target with that mipmap level count is greater than 1 is invalid for
+ color attachments.
+ `
+ )
+ .fn(async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ mipLevelCount: 2 });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('resolveTarget,usage')
+ .desc(
+ `
+ Test that using a resolve target whose usage is not RENDER_ATTACHMENT is invalid for color
+ attachments.
+ `
+ )
+ .paramsSimple([
+ { usage: GPUConst.TextureUsage.COPY_SRC | GPUConst.TextureUsage.COPY_DST },
+ { usage: GPUConst.TextureUsage.STORAGE_BINDING | GPUConst.TextureUsage.TEXTURE_BINDING },
+ { usage: GPUConst.TextureUsage.STORAGE_BINDING | GPUConst.TextureUsage.STORAGE },
+ { usage: GPUConst.TextureUsage.RENDER_ATTACHMENT | GPUConst.TextureUsage.TEXTURE_BINDING },
+ ])
+ .fn(async t => {
+ const { usage } = t.params;
+
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ usage });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ const isValid = usage & GPUConst.TextureUsage.RENDER_ATTACHMENT ? true : false;
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('resolveTarget,error_state')
+ .desc(`Test that a resolve target that has a error is invalid for color attachments.`)
+ .fn(async t => {
+ const ARRAY_LAYER_COUNT = 1;
+
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ arrayLayerCount: ARRAY_LAYER_COUNT });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ t.expectValidationError(() => {
+ colorAttachment.resolveTarget = resolveTargetTexture.createView({
+ dimension: '2d',
+ format: 'rgba8unorm',
+ baseArrayLayer: ARRAY_LAYER_COUNT + 1,
+ });
+ });
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('resolveTarget,single_sample_count')
+ .desc(
+ `
+ Test that a resolve target that has multi sample color attachment and a single resolve target is
+ valid.
+ `
+ )
+ .fn(async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(true, descriptor);
+ });
+
+g.test('resolveTarget,different_format')
+ .desc(`Test that a resolve target that has a different format is invalid.`)
+ .fn(async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ format: 'bgra8unorm' });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ });
+
+g.test('resolveTarget,different_size')
+ .desc(
+ `
+ Test that a resolve target that has a different size with the color attachment is invalid.
+ `
+ )
+ .fn(async t => {
+ const size = 16;
+ const multisampledColorTexture = t.createTexture({ width: size, height: size, sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({
+ width: size * 2,
+ height: size * 2,
+ mipLevelCount: 2,
+ });
+
+ {
+ const resolveTargetTextureView = resolveTargetTexture.createView({
+ baseMipLevel: 0,
+ mipLevelCount: 1,
+ });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTextureView;
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ {
+ const resolveTargetTextureView = resolveTargetTexture.createView({ baseMipLevel: 1 });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTextureView;
+
+ const descriptor = {
+ colorAttachments: [colorAttachment],
+ };
+
+ t.tryRenderPass(true, descriptor);
+ }
+ });
+
+g.test('depth_stencil_attachment,sample_counts_mismatch')
+ .desc(
+ `
+ Test that the depth stencil attachment that has different number of samples with the color
+ attachment is invalid.
+ `
+ )
+ .fn(async t => {
+ const multisampledDepthStencilTexture = t.createTexture({
+ sampleCount: 4,
+ format: 'depth24plus-stencil8',
+ });
+
+ {
+ // It is not allowed to use a depth stencil attachment whose sample count is different from
+ // the one of the color attachment.
+ const depthStencilTexture = t.createTexture({
+ sampleCount: 1,
+ format: 'depth24plus-stencil8',
+ });
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(multisampledColorTexture)],
+ depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture),
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ {
+ const colorTexture = t.createTexture({ sampleCount: 1 });
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ depthStencilAttachment: t.getDepthStencilAttachment(multisampledDepthStencilTexture),
+ };
+
+ t.tryRenderPass(false, descriptor);
+ }
+ {
+ // It is allowed to use a multisampled depth stencil attachment whose sample count is equal to
+ // the one of the color attachment.
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(multisampledColorTexture)],
+ depthStencilAttachment: t.getDepthStencilAttachment(multisampledDepthStencilTexture),
+ };
+
+ t.tryRenderPass(true, descriptor);
+ }
+ {
+ // It is allowed to use a multisampled depth stencil attachment with no color attachment.
+ const descriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(multisampledDepthStencilTexture),
+ };
+
+ t.tryRenderPass(true, descriptor);
+ }
+ });
+
+g.test('depth_stencil_attachment')
+ .desc(
+ `
+ Test GPURenderPassDepthStencilAttachment Usage:
+ - depthReadOnly and stencilReadOnly must match if the format is a combined depth-stencil format.
+ - depthLoadOp and depthStoreOp must be provided iff the format has a depth aspect and
+ depthReadOnly is not true.
+ - stencilLoadOp and stencilStoreOp must be provided iff the format has a stencil aspect and
+ stencilReadOnly is not true.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kDepthStencilFormats)
+ .beginSubcases()
+ .combine('depthReadOnly', [false, true])
+ .combine('stencilReadOnly', [false, true])
+ .combine('setDepthLoadStoreOp', [false, true])
+ .combine('setStencilLoadStoreOp', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const {
+ format,
+ depthReadOnly,
+ stencilReadOnly,
+ setDepthLoadStoreOp,
+ setStencilLoadStoreOp,
+ } = t.params;
+
+ let isValid = true;
+ const info = kTextureFormatInfo[format];
+ if (info.depth && info.stencil) {
+ isValid &&= depthReadOnly === stencilReadOnly;
+ }
+
+ if (info.depth && !depthReadOnly) {
+ isValid &&= setDepthLoadStoreOp;
+ } else {
+ isValid &&= !setDepthLoadStoreOp;
+ }
+
+ if (info.stencil && !stencilReadOnly) {
+ isValid &&= setStencilLoadStoreOp;
+ } else {
+ isValid &&= !setStencilLoadStoreOp;
+ }
+
+ const depthStencilAttachment = {
+ view: t.createTexture({ format }).createView(),
+ depthReadOnly,
+ stencilReadOnly,
+ };
+
+ if (setDepthLoadStoreOp) {
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'store';
+ }
+ if (setStencilLoadStoreOp) {
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'store';
+ }
+
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(t.createTexture())],
+ depthStencilAttachment,
+ };
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('depth_stencil_attachment,depth_clear_value')
+ .desc(
+ `
+ Test that depthClearValue is invalid if the value is out of the range(0.0 and 1.0) only when
+ depthLoadOp is 'clear'.
+ `
+ )
+ .params(u =>
+ u
+ .combine('depthLoadOp', ['load', 'clear', undefined])
+ .combineWithParams([
+ { depthClearValue: -1.0 },
+ { depthClearValue: 0.0 },
+ { depthClearValue: 0.5 },
+ { depthClearValue: 1.0 },
+ { depthClearValue: 1.5 },
+ ])
+ )
+ .fn(t => {
+ const { depthLoadOp, depthClearValue } = t.params;
+
+ const depthStencilTexture = t.createTexture({
+ format: depthLoadOp === undefined ? 'stencil8' : 'depth24plus-stencil8',
+ });
+ const depthStencilAttachment = t.getDepthStencilAttachment(depthStencilTexture);
+ depthStencilAttachment.depthClearValue = depthClearValue;
+ depthStencilAttachment.depthLoadOp = depthLoadOp;
+ if (depthLoadOp === undefined) {
+ depthStencilAttachment.depthStoreOp = undefined;
+ }
+
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(t.createTexture())],
+ depthStencilAttachment,
+ };
+
+ const isValid = !(depthLoadOp === 'clear' && (depthClearValue < 0.0 || depthClearValue > 1.0));
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('resolveTarget,format_supports_resolve')
+ .desc(
+ `
+ For all formats that support 'multisample', test that they can be used as a resolveTarget
+ if and only if they support 'resolve'.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].multisample)
+ )
+ .fn(async t => {
+ const { format } = t.params;
+ const multisampledColorTexture = t.createTexture({ format, sampleCount: 4 });
+ const resolveTarget = t.createTexture({ format });
+
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTarget.createView();
+
+ t.tryRenderPass(kTextureFormatInfo[format].resolve, {
+ colorAttachments: [colorAttachment],
+ });
+ });
+
+g.test('timestampWrites,query_set_type')
+ .desc(
+ `
+ Test that all entries of the timestampWrites must have type 'timestamp'. If all query types are
+ not 'timestamp', a validation error should be generated.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('queryTypeA', kQueryTypes)
+ .combine('queryTypeB', kQueryTypes)
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { queryTypeA, queryTypeB } = t.params;
+
+ const timestampWriteA = {
+ querySet: t.device.createQuerySet({ type: queryTypeA, count: 1 }),
+ queryIndex: 0,
+ location: 'beginning',
+ };
+
+ const timestampWriteB = {
+ querySet: t.device.createQuerySet({ type: queryTypeB, count: 1 }),
+ queryIndex: 0,
+ location: 'end',
+ };
+
+ const isValid = queryTypeA === 'timestamp' && queryTypeB === 'timestamp';
+
+ const colorTexture = t.createTexture();
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ timestampWrites: [timestampWriteA, timestampWriteB],
+ };
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('timestamp_writes_location')
+ .desc('Test that entries in timestampWrites do not have the same location.')
+ .params(u =>
+ u //
+ .combine('locationA', ['beginning', 'end'])
+ .combine('locationB', ['beginning', 'end'])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { locationA, locationB } = t.params;
+
+ const querySet = t.device.createQuerySet({
+ type: 'timestamp',
+ count: 2,
+ });
+
+ const timestampWriteA = {
+ querySet,
+ queryIndex: 0,
+ location: locationA,
+ };
+
+ const timestampWriteB = {
+ querySet,
+ queryIndex: 1,
+ location: locationB,
+ };
+
+ const isValid = locationA !== locationB;
+
+ const colorTexture = t.createTexture({ format: 'rgba8unorm' });
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ timestampWrites: [timestampWriteA, timestampWriteB],
+ };
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('timestampWrite,query_index')
+ .desc(`Test that querySet.count should be greater than timestampWrite.queryIndex.`)
+ .params(u => u.combine('queryIndex', [0, 1, 2, 3]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { queryIndex } = t.params;
+
+ const querySetCount = 2;
+
+ const timestampWrite = {
+ querySet: t.device.createQuerySet({ type: 'timestamp', count: querySetCount }),
+ queryIndex,
+ location: 'beginning',
+ };
+
+ const isValid = queryIndex < querySetCount;
+
+ const colorTexture = t.createTexture();
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ timestampWrites: [timestampWrite],
+ };
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('timestampWrite,same_query_index')
+ .desc(
+ `
+ Test that timestampWrites is invalid if each entry has the same queryIndex in the same querySet.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('queryIndexA', [0, 1])
+ .combine('queryIndexB', [0, 1])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ })
+ .fn(async t => {
+ const { queryIndexA, queryIndexB } = t.params;
+
+ const querySet = t.device.createQuerySet({
+ type: 'timestamp',
+ count: 2,
+ });
+
+ const timestampWriteA = {
+ querySet,
+ queryIndex: queryIndexA,
+ location: 'beginning',
+ };
+
+ const timestampWriteB = {
+ querySet,
+ queryIndex: queryIndexB,
+ location: 'end',
+ };
+
+ const isValid = queryIndexA !== queryIndexB;
+
+ const colorTexture = t.createTexture();
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ timestampWrites: [timestampWriteA, timestampWriteB],
+ };
+
+ t.tryRenderPass(isValid, descriptor);
+ });
+
+g.test('occlusionQuerySet,query_set_type')
+ .desc(`Test that occlusionQuerySet must have type 'occlusion'.`)
+ .params(u => u.combine('queryType', kQueryTypes))
+ .beforeAllSubcases(t => {
+ if (t.params.queryType === 'timestamp') {
+ t.selectDeviceOrSkipTestCase(['timestamp-query']);
+ }
+ })
+ .fn(async t => {
+ const { queryType } = t.params;
+
+ const querySet = t.device.createQuerySet({
+ type: queryType,
+ count: 1,
+ });
+
+ const colorTexture = t.createTexture();
+ const descriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture)],
+ occlusionQuerySet: querySet,
+ };
+
+ const isValid = queryType === 'occlusion';
+ t.tryRenderPass(isValid, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/resolve.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/resolve.spec.js
new file mode 100644
index 0000000000..f586517b23
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/resolve.spec.js
@@ -0,0 +1,193 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Validation tests for render pass resolve.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../constants.js';
+import { ValidationTest } from '../validation_test.js';
+
+const kNumColorAttachments = 4;
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('resolve_attachment')
+ .desc(
+ `
+Test various validation behaviors when a resolveTarget is provided.
+
+- base case (valid).
+- resolve source is not multisampled.
+- resolve target is not single sampled.
+- resolve target missing RENDER_ATTACHMENT usage.
+- resolve target must have exactly one subresource:
+ - base mip level {0, >0}, mip level count {1, >1}.
+ - base array layer {0, >0}, array layer count {1, >1}.
+- resolve target GPUTextureView is invalid
+- resolve source and target have different formats.
+ - rgba8unorm -> {bgra8unorm, rgba8unorm-srgb}
+ - {bgra8unorm, rgba8unorm-srgb} -> rgba8unorm
+ - test with other color attachments having a different format
+- resolve source and target have different sizes.
+`
+ )
+ .paramsSimple([
+ // control case should be valid
+ { _valid: true },
+ // a single sampled resolve source should cause a validation error.
+ { colorAttachmentSamples: 1, _valid: false },
+ // a multisampled resolve target should cause a validation error.
+ { resolveTargetSamples: 4, _valid: false },
+ // resolveTargetUsage without RENDER_ATTACHMENT usage should cause a validation error.
+ { resolveTargetUsage: GPUConst.TextureUsage.COPY_SRC, _valid: false },
+ // non-zero resolve target base mip level should be valid.
+ {
+ resolveTargetViewBaseMipLevel: 1,
+ resolveTargetHeight: 4,
+ resolveTargetWidth: 4,
+ _valid: true,
+ },
+ // a validation error should be created when resolveTarget is invalid.
+ { resolveTargetInvalid: true, _valid: false },
+ // a validation error should be created when mip count > 1
+ { resolveTargetViewMipCount: 2, _valid: false },
+ {
+ resolveTargetViewBaseMipLevel: 1,
+ resolveTargetViewMipCount: 2,
+ resolveTargetHeight: 4,
+ resolveTargetWidth: 4,
+ _valid: false,
+ },
+ // non-zero resolve target base array layer should be valid.
+ { resolveTargetViewBaseArrayLayer: 1, _valid: true },
+ // a validation error should be created when array layer count > 1
+ { resolveTargetViewArrayLayerCount: 2, _valid: false },
+ { resolveTargetViewBaseArrayLayer: 1, resolveTargetViewArrayLayerCount: 2, _valid: false },
+ // other color attachments resolving with a different format should be valid.
+ { otherAttachmentFormat: 'bgra8unorm', _valid: true },
+ // mismatched colorAttachment and resolveTarget formats should cause a validation error.
+ { colorAttachmentFormat: 'bgra8unorm', _valid: false },
+ { colorAttachmentFormat: 'rgba8unorm-srgb', _valid: false },
+ { resolveTargetFormat: 'bgra8unorm', _valid: false },
+ { resolveTargetFormat: 'rgba8unorm-srgb', _valid: false },
+ // mismatched colorAttachment and resolveTarget sizes should cause a validation error.
+ { colorAttachmentHeight: 4, _valid: false },
+ { colorAttachmentWidth: 4, _valid: false },
+ { resolveTargetHeight: 4, _valid: false },
+ { resolveTargetWidth: 4, _valid: false },
+ ])
+ .fn(async t => {
+ const {
+ colorAttachmentFormat = 'rgba8unorm',
+ resolveTargetFormat = 'rgba8unorm',
+ otherAttachmentFormat = 'rgba8unorm',
+ colorAttachmentSamples = 4,
+ resolveTargetSamples = 1,
+ resolveTargetUsage = GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ resolveTargetInvalid = false,
+ resolveTargetViewMipCount = 1,
+ resolveTargetViewBaseMipLevel = 0,
+ resolveTargetViewArrayLayerCount = 1,
+ resolveTargetViewBaseArrayLayer = 0,
+ colorAttachmentHeight = 2,
+ colorAttachmentWidth = 2,
+ resolveTargetHeight = 2,
+ resolveTargetWidth = 2,
+ _valid,
+ } = t.params;
+
+ // Run the test in a nested loop such that the configured color attachment with resolve target
+ // is tested while occupying each individual colorAttachment slot.
+ for (let resolveSlot = 0; resolveSlot < kNumColorAttachments; resolveSlot++) {
+ const renderPassColorAttachmentDescriptors = [];
+ for (
+ let colorAttachmentSlot = 0;
+ colorAttachmentSlot < kNumColorAttachments;
+ colorAttachmentSlot++
+ ) {
+ // resolveSlot === colorAttachmentSlot denotes the color attachment slot that contains the
+ // color attachment with resolve target.
+ if (resolveSlot === colorAttachmentSlot) {
+ // Create the color attachment with resolve target with the configurable parameters.
+ const resolveSourceColorAttachment = t.device.createTexture({
+ format: colorAttachmentFormat,
+ size: {
+ width: colorAttachmentWidth,
+ height: colorAttachmentHeight,
+ depthOrArrayLayers: 1,
+ },
+ sampleCount: colorAttachmentSamples,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const resolveTarget = t.device.createTexture({
+ format: resolveTargetFormat,
+ size: {
+ width: resolveTargetWidth,
+ height: resolveTargetHeight,
+ depthOrArrayLayers:
+ resolveTargetViewBaseArrayLayer + resolveTargetViewArrayLayerCount,
+ },
+ sampleCount: resolveTargetSamples,
+ mipLevelCount: resolveTargetViewBaseMipLevel + resolveTargetViewMipCount,
+ usage: resolveTargetUsage,
+ });
+
+ renderPassColorAttachmentDescriptors.push({
+ view: resolveSourceColorAttachment.createView(),
+ loadOp: 'load',
+ storeOp: 'discard',
+ resolveTarget: resolveTargetInvalid
+ ? t.getErrorTextureView()
+ : resolveTarget.createView({
+ dimension: resolveTargetViewArrayLayerCount === 1 ? '2d' : '2d-array',
+ mipLevelCount: resolveTargetViewMipCount,
+ arrayLayerCount: resolveTargetViewArrayLayerCount,
+ baseMipLevel: resolveTargetViewBaseMipLevel,
+ baseArrayLayer: resolveTargetViewBaseArrayLayer,
+ }),
+ });
+ } else {
+ // Create a basic texture to fill other color attachment slots. This texture's dimensions
+ // and sample count must match the resolve source color attachment to be valid.
+ const colorAttachment = t.device.createTexture({
+ format: otherAttachmentFormat,
+ size: {
+ width: colorAttachmentWidth,
+ height: colorAttachmentHeight,
+ depthOrArrayLayers: 1,
+ },
+ sampleCount: colorAttachmentSamples,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const resolveTarget = t.device.createTexture({
+ format: otherAttachmentFormat,
+ size: {
+ width: colorAttachmentWidth,
+ height: colorAttachmentHeight,
+ depthOrArrayLayers: 1,
+ },
+ sampleCount: 1,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ renderPassColorAttachmentDescriptors.push({
+ view: colorAttachment.createView(),
+ loadOp: 'load',
+ storeOp: 'discard',
+ resolveTarget: resolveTarget.createView(),
+ });
+ }
+ }
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: renderPassColorAttachmentDescriptors,
+ });
+ pass.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !_valid);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/storeOp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/storeOp.spec.js
new file mode 100644
index 0000000000..685830300f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pass/storeOp.spec.js
@@ -0,0 +1,76 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+API Validation Tests for RenderPass StoreOp.
+
+Test Coverage:
+ - Tests that when depthReadOnly is true, depthStoreOp must be 'store'.
+ - When depthReadOnly is true and depthStoreOp is 'discard', an error should be generated.
+
+ - Tests that when stencilReadOnly is true, stencilStoreOp must be 'store'.
+ - When stencilReadOnly is true and stencilStoreOp is 'discard', an error should be generated.
+
+ - Tests that the depthReadOnly value matches the stencilReadOnly value.
+ - When depthReadOnly does not match stencilReadOnly, an error should be generated.
+
+ - Tests that depthReadOnly and stencilReadOnly default to false.
+
+TODO: test interactions with depthClearValue too
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('store_op_and_read_only')
+ .paramsSimple([
+ { readonly: true, _valid: true },
+ // Using depthReadOnly=true and depthStoreOp='discard' should cause a validation error.
+ { readonly: true, depthStoreOp: 'discard', _valid: false },
+ // Using stencilReadOnly=true and stencilStoreOp='discard' should cause a validation error.
+ { readonly: true, stencilStoreOp: 'discard', _valid: false },
+ // Mismatched depthReadOnly and stencilReadOnly values should cause a validation error.
+ { readonly: false, _valid: true },
+ { readonly: false, depthReadOnly: true, _valid: false },
+ { readonly: false, stencilReadOnly: true, _valid: false },
+ // depthReadOnly and stencilReadOnly should default to false.
+ { readonly: undefined, _valid: true },
+ { readonly: undefined, depthReadOnly: true, _valid: false },
+ { readonly: undefined, stencilReadOnly: true, _valid: false },
+ ])
+ .fn(async t => {
+ const {
+ readonly,
+ depthStoreOp = 'store',
+ depthReadOnly = readonly,
+ stencilStoreOp = 'store',
+ stencilReadOnly = readonly,
+ _valid,
+ } = t.params;
+
+ const depthAttachment = t.device.createTexture({
+ format: 'depth24plus-stencil8',
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const depthAttachmentView = depthAttachment.createView();
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: depthAttachmentView,
+ depthLoadOp: 'load',
+ depthStoreOp,
+ depthReadOnly,
+ stencilLoadOp: 'load',
+ stencilStoreOp,
+ stencilReadOnly,
+ },
+ });
+ pass.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !_valid);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js
new file mode 100644
index 0000000000..3fcfbc52b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/common.js
@@ -0,0 +1,62 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { kTextureFormatInfo } from '../../../capability_info.js';
+import {
+ getFragmentShaderCodeWithOutput,
+ getPlainTypeInfo,
+ kDefaultVertexShaderCode,
+} from '../../../util/shader.js';
+import { ValidationTest } from '../validation_test.js';
+
+const values = [0, 1, 0, 1];
+export class CreateRenderPipelineValidationTest extends ValidationTest {
+ getDescriptor(options = {}) {
+ const defaultTargets = [{ format: 'rgba8unorm' }];
+ const {
+ primitive = {},
+ targets = defaultTargets,
+ multisample = {},
+ depthStencil,
+ fragmentShaderCode = getFragmentShaderCodeWithOutput([
+ {
+ values,
+ plainType: getPlainTypeInfo(
+ kTextureFormatInfo[targets[0] ? targets[0].format : 'rgba8unorm'].sampleType
+ ),
+
+ componentCount: 4,
+ },
+ ]),
+
+ noFragment = false,
+ fragmentConstants = {},
+ } = options;
+
+ return {
+ vertex: {
+ module: this.device.createShaderModule({
+ code: kDefaultVertexShaderCode,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: noFragment
+ ? undefined
+ : {
+ module: this.device.createShaderModule({
+ code: fragmentShaderCode,
+ }),
+ entryPoint: 'main',
+ targets,
+ constants: fragmentConstants,
+ },
+ layout: this.getPipelineLayout(),
+ primitive,
+ multisample,
+ depthStencil,
+ };
+ }
+
+ getPipelineLayout() {
+ return this.device.createPipelineLayout({ bindGroupLayouts: [] });
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js
new file mode 100644
index 0000000000..0f027e1200
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.js
@@ -0,0 +1,205 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of GPUDepthStencilState of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../common/util/util.js';
+import {
+ kTextureFormats,
+ kTextureFormatInfo,
+ kDepthStencilFormats,
+ kCompareFunctions,
+ kStencilOperations,
+} from '../../../capability_info.js';
+import { getFragmentShaderCodeWithOutput } from '../../../util/shader.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('format')
+ .desc(`The texture format in depthStencilState must be a depth/stencil format.`)
+ .params(u => u.combine('isAsync', [false, true]).combine('format', kTextureFormats))
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({ depthStencil: { format } });
+
+ t.doCreateRenderPipelineTest(isAsync, info.depth || info.stencil, descriptor);
+ });
+
+g.test('depth_test')
+ .desc(
+ `Depth aspect must be contained in the format if depth test is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('depthCompare', [undefined, ...kCompareFunctions])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, depthCompare } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ depthStencil: { format, depthCompare },
+ });
+
+ const depthTestEnabled = depthCompare !== undefined && depthCompare !== 'always';
+ t.doCreateRenderPipelineTest(isAsync, !depthTestEnabled || info.depth, descriptor);
+ });
+
+g.test('depth_write')
+ .desc(
+ `Depth aspect must be contained in the format if depth write is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('depthWriteEnabled', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, depthWriteEnabled } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ depthStencil: { format, depthWriteEnabled },
+ });
+ t.doCreateRenderPipelineTest(isAsync, !depthWriteEnabled || info.depth, descriptor);
+ });
+
+g.test('depth_write,frag_depth')
+ .desc(`Depth aspect must be contained in the format if frag_depth is written in fragment stage.`)
+ .params(u =>
+ u.combine('isAsync', [false, true]).combine('format', [undefined, ...kDepthStencilFormats])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ if (format !== undefined) {
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ }
+ })
+ .fn(async t => {
+ const { isAsync, format } = t.params;
+
+ const descriptor = t.getDescriptor({
+ // Keep one color target so that the pipeline is still valid with no depth stencil target.
+ targets: [{ format: 'rgba8unorm' }],
+ depthStencil: format ? { format, depthWriteEnabled: true } : undefined,
+ fragmentShaderCode: getFragmentShaderCodeWithOutput(
+ [{ values: [1, 1, 1, 1], plainType: 'f32', componentCount: 4 }],
+ { value: 0.5 }
+ ),
+ });
+
+ const hasDepth = format ? kTextureFormatInfo[format].depth : false;
+ t.doCreateRenderPipelineTest(isAsync, hasDepth, descriptor);
+ });
+
+g.test('stencil_test')
+ .desc(
+ `Stencil aspect must be contained in the format if stencil test is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('face', ['front', 'back'])
+ .combine('compare', [undefined, ...kCompareFunctions])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, face, compare } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ let descriptor;
+ if (face === 'front') {
+ descriptor = t.getDescriptor({ depthStencil: { format, stencilFront: { compare } } });
+ } else {
+ descriptor = t.getDescriptor({ depthStencil: { format, stencilBack: { compare } } });
+ }
+
+ const stencilTestEnabled = compare !== undefined && compare !== 'always';
+ t.doCreateRenderPipelineTest(isAsync, !stencilTestEnabled || info.stencil, descriptor);
+ });
+
+g.test('stencil_write')
+ .desc(
+ `Stencil aspect must be contained in the format if stencil write is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('faceAndOpType', [
+ 'frontFailOp',
+ 'frontDepthFailOp',
+ 'frontPassOp',
+ 'backFailOp',
+ 'backDepthFailOp',
+ 'backPassOp',
+ ])
+ .combine('op', [undefined, ...kStencilOperations])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, faceAndOpType, op } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ let depthStencil;
+ switch (faceAndOpType) {
+ case 'frontFailOp':
+ depthStencil = { format, stencilFront: { failOp: op } };
+ break;
+ case 'frontDepthFailOp':
+ depthStencil = { format, stencilFront: { depthFailOp: op } };
+ break;
+ case 'frontPassOp':
+ depthStencil = { format, stencilFront: { passOp: op } };
+ break;
+ case 'backFailOp':
+ depthStencil = { format, stencilBack: { failOp: op } };
+ break;
+ case 'backDepthFailOp':
+ depthStencil = { format, stencilBack: { depthFailOp: op } };
+ break;
+ case 'backPassOp':
+ depthStencil = { format, stencilBack: { passOp: op } };
+ break;
+ default:
+ unreachable();
+ }
+
+ const descriptor = t.getDescriptor({ depthStencil });
+
+ const stencilWriteEnabled = op !== undefined && op !== 'keep';
+ t.doCreateRenderPipelineTest(isAsync, !stencilWriteEnabled || info.stencil, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js
new file mode 100644
index 0000000000..2f0bb4ed8e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/fragment_state.spec.js
@@ -0,0 +1,385 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of GPUFragmentState of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { range } from '../../../../common/util/util.js';
+import {
+ kTextureFormats,
+ kRenderableColorTextureFormats,
+ kTextureFormatInfo,
+ kBlendFactors,
+ kBlendOperations,
+ kMaxColorAttachments,
+} from '../../../capability_info.js';
+import {
+ getFragmentShaderCodeWithOutput,
+ getPlainTypeInfo,
+ kDefaultFragmentShaderCode,
+} from '../../../util/shader.js';
+import { kTexelRepresentationInfo } from '../../../util/texture/texel_data.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+const values = [0, 1, 0, 1];
+
+g.test('color_target_exists')
+ .desc(`Tests creating a complete render pipeline requires at least one color target state.`)
+ .params(u => u.combine('isAsync', [false, true]))
+ .fn(async t => {
+ const { isAsync } = t.params;
+
+ const goodDescriptor = t.getDescriptor({
+ targets: [{ format: 'rgba8unorm' }],
+ });
+
+ // Control case
+ t.doCreateRenderPipelineTest(isAsync, true, goodDescriptor);
+
+ // Fail because lack of color states
+ const badDescriptor = t.getDescriptor({
+ targets: [],
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, false, badDescriptor);
+ });
+
+g.test('targets_format_renderable')
+ .desc(`Tests that color target state format must have RENDER_ATTACHMENT capability.`)
+ .params(u => u.combine('isAsync', [false, true]).combine('format', kTextureFormats))
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({ targets: [{ format }] });
+
+ t.doCreateRenderPipelineTest(isAsync, info.renderable && info.color, descriptor);
+ });
+
+g.test('limits,maxColorAttachments')
+ .desc(
+ `Tests that color state targets length must not be larger than device.limits.maxColorAttachments.`
+ )
+ .params(u => u.combine('isAsync', [false, true]).combine('targetsLength', [8, 9]))
+ .fn(async t => {
+ const { isAsync, targetsLength } = t.params;
+
+ const descriptor = t.getDescriptor({
+ targets: range(targetsLength, i => {
+ // Set writeMask to 0 for attachments without fragment output
+ return { format: 'rg8unorm', writeMask: i === 0 ? 0xf : 0 };
+ }),
+ fragmentShaderCode: kDefaultFragmentShaderCode,
+ });
+
+ t.doCreateRenderPipelineTest(
+ isAsync,
+ targetsLength <= t.device.limits.maxColorAttachments,
+ descriptor
+ );
+ });
+
+g.test('limits,maxColorAttachmentBytesPerSample,aligned')
+ .desc(
+ `
+ Tests that the total color attachment bytes per sample must not be larger than
+ maxColorAttachmentBytesPerSample when using the same format for multiple attachments.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine(
+ 'attachmentCount',
+ range(kMaxColorAttachments, i => i + 1)
+ )
+ .combine('isAsync', [false, true])
+ )
+ .fn(async t => {
+ const { format, attachmentCount, isAsync } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ targets: range(attachmentCount, () => {
+ return { format, writeMask: 0 };
+ }),
+ });
+ const shouldError =
+ info.renderTargetPixelByteCost === undefined ||
+ info.renderTargetPixelByteCost * attachmentCount >
+ t.device.limits.maxColorAttachmentBytesPerSample;
+
+ t.doCreateRenderPipelineTest(isAsync, !shouldError, descriptor);
+ });
+
+g.test('limits,maxColorAttachmentBytesPerSample,unaligned')
+ .desc(
+ `
+ Tests that the total color attachment bytes per sample must not be larger than
+ maxColorAttachmentBytesPerSample when using various sets of (potentially) unaligned formats.
+ `
+ )
+ .params(u =>
+ u
+ .combineWithParams([
+ // Alignment causes the first 1 byte R8Unorm to become 4 bytes. So even though
+ // 1+4+8+16+1 < 32, the 4 byte alignment requirement of R32Float makes the first R8Unorm
+ // become 4 and 4+4+8+16+1 > 32. Re-ordering this so the R8Unorm's are at the end, however
+ // is allowed: 4+8+16+1+1 < 32.
+ {
+ formats: ['r8unorm', 'r32float', 'rgba8unorm', 'rgba32float', 'r8unorm'],
+
+ _success: true,
+ },
+ {
+ formats: ['r32float', 'rgba8unorm', 'rgba32float', 'r8unorm', 'r8unorm'],
+
+ _success: false,
+ },
+ ])
+ .beginSubcases()
+ .combine('isAsync', [false, true])
+ )
+ .fn(async t => {
+ const { formats, _success, isAsync } = t.params;
+
+ const descriptor = t.getDescriptor({
+ targets: formats.map(f => {
+ return { format: f, writeMask: 0 };
+ }),
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('targets_format_filterable')
+ .desc(`Tests that color target state format must be filterable if blend is not undefined.`)
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine('hasBlend', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, hasBlend } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ targets: [
+ {
+ format,
+ blend: hasBlend ? { color: {}, alpha: {} } : undefined,
+ },
+ ],
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, !hasBlend || info.sampleType === 'float', descriptor);
+ });
+
+g.test('targets_blend')
+ .desc(
+ `
+ For the blend components on either GPUBlendState.color or GPUBlendState.alpha:
+ - Tests if the combination of 'srcFactor', 'dstFactor' and 'operation' is valid (if the blend
+ operation is "min" or "max", srcFactor and dstFactor must be "one").
+ `
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('component', ['color', 'alpha'])
+ .beginSubcases()
+ .combine('srcFactor', kBlendFactors)
+ .combine('dstFactor', kBlendFactors)
+ .combine('operation', kBlendOperations)
+ )
+ .fn(async t => {
+ const { isAsync, component, srcFactor, dstFactor, operation } = t.params;
+
+ const defaultBlendComponent = {
+ srcFactor: 'src-alpha',
+ dstFactor: 'dst-alpha',
+ operation: 'add',
+ };
+ const blendComponentToTest = {
+ srcFactor,
+ dstFactor,
+ operation,
+ };
+ const format = 'rgba8unorm';
+
+ const descriptor = t.getDescriptor({
+ targets: [
+ {
+ format,
+ blend: {
+ color: component === 'color' ? blendComponentToTest : defaultBlendComponent,
+ alpha: component === 'alpha' ? blendComponentToTest : defaultBlendComponent,
+ },
+ },
+ ],
+ });
+
+ if (operation === 'min' || operation === 'max') {
+ const _success = srcFactor === 'one' && dstFactor === 'one';
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ } else {
+ t.doCreateRenderPipelineTest(isAsync, true, descriptor);
+ }
+ });
+
+g.test('targets_write_mask')
+ .desc(`Tests that color target state write mask must be < 16.`)
+ .params(u => u.combine('isAsync', [false, true]).combine('writeMask', [0, 0xf, 0x10, 0x80000001]))
+ .fn(async t => {
+ const { isAsync, writeMask } = t.params;
+
+ const descriptor = t.getDescriptor({
+ targets: [
+ {
+ format: 'rgba8unorm',
+ writeMask,
+ },
+ ],
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, writeMask < 16, descriptor);
+ });
+
+g.test('pipeline_output_targets')
+ .desc(
+ `Pipeline fragment output types must be compatible with target color state format
+ - The scalar type (f32, i32, or u32) must match the sample type of the format.
+ - The componentCount of the fragment output (e.g. f32, vec2, vec3, vec4) must not have fewer
+ channels than that of the color attachment texture formats. Extra components are allowed and are discarded.
+
+ Otherwise, color state write mask must be 0.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', [undefined, ...kRenderableColorTextureFormats])
+ .beginSubcases()
+ .combine('shaderOutput', [
+ undefined,
+ ...u.combine('scalar', ['f32', 'u32', 'i32']).combine('count', [1, 2, 3, 4]),
+ ])
+
+ // We only care about testing writeMask if there is an attachment but no shader output.
+ .expand('writeMask', p =>
+ p.format !== undefined && p.shaderOutput !== undefined ? [0, 0x1, 0x2, 0x4, 0x8] : [0xf]
+ )
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { isAsync, format, writeMask, shaderOutput } = t.params;
+
+ const descriptor = t.getDescriptor({
+ targets: format ? [{ format, writeMask }] : [],
+ // To have a dummy depthStencil attachment to avoid having no attachment at all which is invalid
+ depthStencil: { format: 'depth24plus' },
+ fragmentShaderCode: getFragmentShaderCodeWithOutput(
+ shaderOutput
+ ? [{ values, plainType: shaderOutput.scalar, componentCount: shaderOutput.count }]
+ : []
+ ),
+ });
+
+ let success = true;
+ if (format) {
+ // There is a color target
+ if (shaderOutput) {
+ // The shader outputs to the color target
+ const info = kTextureFormatInfo[format];
+ success =
+ shaderOutput.scalar === getPlainTypeInfo(info.sampleType) &&
+ shaderOutput.count >= kTexelRepresentationInfo[format].componentOrder.length;
+ } else {
+ // The shader does not output to the color target
+ success = writeMask === 0;
+ }
+ }
+
+ t.doCreateRenderPipelineTest(isAsync, success, descriptor);
+ });
+
+g.test('pipeline_output_targets,blend')
+ .desc(
+ `On top of requirements from pipeline_output_targets, when blending is enabled and alpha channel is read indicated by any blend factor, an extra requirement is added:
+ - fragment output must be vec4.
+ `
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', ['r8unorm', 'rg8unorm', 'rgba8unorm', 'bgra8unorm'])
+ .combine('componentCount', [1, 2, 3, 4])
+ .beginSubcases()
+ // The default srcFactor and dstFactor are 'one' and 'zero'. Override just one at a time.
+ .combineWithParams([
+ ...u.combine('colorSrcFactor', kBlendFactors),
+ ...u.combine('colorDstFactor', kBlendFactors),
+ ...u.combine('alphaSrcFactor', kBlendFactors),
+ ...u.combine('alphaDstFactor', kBlendFactors),
+ ])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const sampleType = 'float';
+ const {
+ isAsync,
+ format,
+ componentCount,
+ colorSrcFactor,
+ colorDstFactor,
+ alphaSrcFactor,
+ alphaDstFactor,
+ } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ targets: [
+ {
+ format,
+ blend: {
+ color: { srcFactor: colorSrcFactor, dstFactor: colorDstFactor },
+ alpha: { srcFactor: alphaSrcFactor, dstFactor: alphaDstFactor },
+ },
+ },
+ ],
+
+ fragmentShaderCode: getFragmentShaderCodeWithOutput([
+ { values, plainType: getPlainTypeInfo(sampleType), componentCount },
+ ]),
+ });
+
+ const colorBlendReadsSrcAlpha =
+ colorSrcFactor?.includes('src-alpha') || colorDstFactor?.includes('src-alpha');
+ const meetsExtraBlendingRequirement = !colorBlendReadsSrcAlpha || componentCount === 4;
+ const _success =
+ info.sampleType === sampleType &&
+ componentCount >= kTexelRepresentationInfo[format].componentOrder.length &&
+ meetsExtraBlendingRequirement;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js
new file mode 100644
index 0000000000..9befb1aa3d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/inter_stage.spec.js
@@ -0,0 +1,320 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Interface matching between vertex and fragment shader validation for createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, range } from '../../../../common/util/util.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+function getVarName(i) {
+ return `v${i}`;
+}
+
+class InterStageMatchingValidationTest extends CreateRenderPipelineValidationTest {
+ getVertexStateWithOutputs(outputs) {
+ return {
+ module: this.device.createShaderModule({
+ code: `
+ struct A {
+ ${outputs.map((v, i) => v.replace('__', getVarName(i))).join(',\n')},
+ @builtin(position) pos: vec4<f32>,
+ }
+ @vertex fn main() -> A {
+ var vertexOut: A;
+ vertexOut.pos = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ return vertexOut;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ };
+ }
+
+ getFragmentStateWithInputs(inputs, hasBuiltinPosition = false) {
+ return {
+ targets: [{ format: 'rgba8unorm' }],
+ module: this.device.createShaderModule({
+ code: `
+ struct B {
+ ${inputs.map((v, i) => v.replace('__', getVarName(i))).join(',\n')},
+ ${hasBuiltinPosition ? '@builtin(position) pos: vec4<f32>' : ''}
+ }
+ @fragment fn main(fragmentIn: B) -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ };
+ }
+
+ getDescriptorWithStates(vertex, fragment) {
+ return {
+ layout: 'auto',
+ vertex,
+ fragment,
+ };
+ }
+}
+
+export const g = makeTestGroup(InterStageMatchingValidationTest);
+
+g.test('location,mismatch')
+ .desc(`Tests that missing declaration at the same location should fail validation.`)
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ { outputs: ['@location(0) __: f32'], inputs: ['@location(0) __: f32'], _success: true },
+ { outputs: ['@location(0) __: f32'], inputs: ['@location(1) __: f32'], _success: false },
+ { outputs: ['@location(1) __: f32'], inputs: ['@location(0) __: f32'], _success: false },
+ {
+ outputs: ['@location(0) __: f32', '@location(1) __: f32'],
+ inputs: ['@location(1) __: f32', '@location(0) __: f32'],
+ _success: true,
+ },
+ {
+ outputs: ['@location(1) __: f32', '@location(0) __: f32'],
+ inputs: ['@location(0) __: f32', '@location(1) __: f32'],
+ _success: true,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, outputs, inputs, _success } = t.params;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs(outputs),
+ t.getFragmentStateWithInputs(inputs)
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('location,superset')
+ .desc(`TODO: implement after spec is settled: https://github.com/gpuweb/gpuweb/issues/2038`)
+ .unimplemented();
+
+g.test('location,subset')
+ .desc(`Tests that validation should fail when vertex output is a subset of fragment input.`)
+ .params(u => u.combine('isAsync', [false, true]))
+ .fn(async t => {
+ const { isAsync } = t.params;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs(['@location(0) vout0: f32']),
+ t.getFragmentStateWithInputs(['@location(0) fin0: f32', '@location(1) fin1: f32'])
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, false, descriptor);
+ });
+
+g.test('type')
+ .desc(
+ `Tests that validation should fail when type of vertex output and fragment input at the same location doesn't match.`
+ )
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ { output: 'f32', input: 'f32' },
+ { output: 'i32', input: 'f32' },
+ { output: 'u32', input: 'f32' },
+ { output: 'u32', input: 'i32' },
+ { output: 'i32', input: 'u32' },
+ { output: 'vec2<f32>', input: 'vec2<f32>' },
+ { output: 'vec3<f32>', input: 'vec2<f32>' },
+ { output: 'vec2<f32>', input: 'vec3<f32>' },
+ { output: 'vec2<f32>', input: 'f32' },
+ { output: 'f32', input: 'vec2<f32>' },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, output, input } = t.params;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs([`@location(0) @interpolate(flat) vout0: ${output}`]),
+ t.getFragmentStateWithInputs([`@location(0) @interpolate(flat) fin0: ${input}`])
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, output === input, descriptor);
+ });
+
+g.test('interpolation_type')
+ .desc(
+ `Tests that validation should fail when interpolation type of vertex output and fragment input at the same location doesn't match.`
+ )
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ // default is @interpolate(perspective, center)
+ { output: '', input: '' },
+ { output: '', input: '@interpolate(perspective)', _success: true },
+ { output: '', input: '@interpolate(perspective, center)', _success: true },
+ { output: '@interpolate(perspective)', input: '', _success: true },
+ { output: '', input: '@interpolate(linear)' },
+ { output: '@interpolate(perspective)', input: '@interpolate(perspective)' },
+ { output: '@interpolate(linear)', input: '@interpolate(perspective)' },
+ { output: '@interpolate(flat)', input: '@interpolate(perspective)' },
+ { output: '@interpolate(linear)', input: '@interpolate(flat)' },
+ { output: '@interpolate(linear, center)', input: '@interpolate(linear, center)' },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, output, input, _success } = t.params;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs([`@location(0) ${output} vout0: f32`]),
+ t.getFragmentStateWithInputs([`@location(0) ${input} fin0: f32`])
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, _success ?? output === input, descriptor);
+ });
+
+g.test('interpolation_sampling')
+ .desc(
+ `Tests that validation should fail when interpolation sampling of vertex output and fragment input at the same location doesn't match.`
+ )
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ // default is @interpolate(perspective, center)
+ { output: '@interpolate(perspective)', input: '@interpolate(perspective)' },
+ {
+ output: '@interpolate(perspective)',
+ input: '@interpolate(perspective, center)',
+ _success: true,
+ },
+ { output: '@interpolate(linear, center)', input: '@interpolate(linear)', _success: true },
+ { output: '@interpolate(flat)', input: '@interpolate(flat)' },
+ { output: '@interpolate(perspective)', input: '@interpolate(perspective, sample)' },
+ { output: '@interpolate(perspective, center)', input: '@interpolate(perspective, sample)' },
+ {
+ output: '@interpolate(perspective, center)',
+ input: '@interpolate(perspective, centroid)',
+ },
+ { output: '@interpolate(perspective, centroid)', input: '@interpolate(perspective)' },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, output, input, _success } = t.params;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs([`@location(0) ${output} vout0: f32`]),
+ t.getFragmentStateWithInputs([`@location(0) ${input} fin0: f32`])
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, _success ?? output === input, descriptor);
+ });
+
+g.test('max_shader_variable_location')
+ .desc(
+ `Tests that validation should fail when there is location of user-defined output/input variable >= device.limits.maxInterStageShaderVariables`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ // User defined variable location = maxInterStageShaderVariables + locationDelta
+ .combine('locationDelta', [0, -1, -2])
+ )
+ .fn(async t => {
+ const { isAsync, locationDelta } = t.params;
+ const maxInterStageShaderVariables = t.device.limits.maxInterStageShaderVariables;
+ const location = maxInterStageShaderVariables + locationDelta;
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs([`@location(${location}) vout0: f32`]),
+ t.getFragmentStateWithInputs([`@location(${location}) fin0: f32`])
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, location < maxInterStageShaderVariables, descriptor);
+ });
+
+g.test('max_components_count,output')
+ .desc(
+ `Tests that validation should fail when scalar components of all user-defined outputs > max vertex shader output components.`
+ )
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ // Number of user-defined output scalar components in test shader = device.limits.maxInterStageShaderComponents + numScalarDelta.
+ { numScalarDelta: 0, topology: 'triangle-list', _success: true },
+ { numScalarDelta: 1, topology: 'triangle-list', _success: false },
+ { numScalarDelta: 0, topology: 'point-list', _success: false },
+ { numScalarDelta: -1, topology: 'point-list', _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, numScalarDelta, topology, _success } = t.params;
+
+ const numScalarComponents = t.device.limits.maxInterStageShaderComponents + numScalarDelta;
+
+ const numVec4 = Math.floor(numScalarComponents / 4);
+ const numTrailingScalars = numScalarComponents % 4;
+ const numUserDefinedInterStageVariables = numTrailingScalars > 0 ? numVec4 + 1 : numVec4;
+
+ assert(numUserDefinedInterStageVariables <= t.device.limits.maxInterStageShaderVariables);
+
+ const outputs = range(numVec4, i => `@location(${i}) vout${i}: vec4<f32>`);
+ const inputs = range(numVec4, i => `@location(${i}) fin${i}: vec4<f32>`);
+
+ if (numTrailingScalars > 0) {
+ const typeString = numTrailingScalars === 1 ? 'f32' : `vec${numTrailingScalars}<f32>`;
+ outputs.push(`@location(${numVec4}) vout${numVec4}: ${typeString}`);
+ inputs.push(`@location(${numVec4}) fin${numVec4}: ${typeString}`);
+ }
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs(outputs),
+ t.getFragmentStateWithInputs(inputs)
+ );
+
+ descriptor.primitive = { topology };
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('max_components_count,input')
+ .desc(
+ `Tests that validation should fail when scalar components of all user-defined inputs > max vertex shader output components.`
+ )
+ .params(u =>
+ u.combine('isAsync', [false, true]).combineWithParams([
+ // Number of user-defined input scalar components in test shader = device.limits.maxInterStageShaderComponents + numScalarDelta.
+ { numScalarDelta: 0, useExtraBuiltinInputs: false, _success: true },
+ { numScalarDelta: 1, useExtraBuiltinInputs: false, _success: false },
+ { numScalarDelta: 0, useExtraBuiltinInputs: true, _success: false },
+ { numScalarDelta: -3, useExtraBuiltinInputs: true, _success: true },
+ { numScalarDelta: -2, useExtraBuiltinInputs: true, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, numScalarDelta, useExtraBuiltinInputs, _success } = t.params;
+
+ const numScalarComponents = t.device.limits.maxInterStageShaderComponents + numScalarDelta;
+
+ const numVec4 = Math.floor(numScalarComponents / 4);
+ const numTrailingScalars = numScalarComponents % 4;
+ const numUserDefinedInterStageVariables = numTrailingScalars > 0 ? numVec4 + 1 : numVec4;
+
+ assert(numUserDefinedInterStageVariables <= t.device.limits.maxInterStageShaderVariables);
+
+ const outputs = range(numVec4, i => `@location(${i}) vout${i}: vec4<f32>`);
+ const inputs = range(numVec4, i => `@location(${i}) fin${i}: vec4<f32>`);
+
+ if (numTrailingScalars > 0) {
+ const typeString = numTrailingScalars === 1 ? 'f32' : `vec${numTrailingScalars}<f32>`;
+ outputs.push(`@location(${numVec4}) vout${numVec4}: ${typeString}`);
+ inputs.push(`@location(${numVec4}) fin${numVec4}: ${typeString}`);
+ }
+
+ if (useExtraBuiltinInputs) {
+ inputs.push(
+ '@builtin(front_facing) front_facing_in: bool',
+ '@builtin(sample_index) sample_index_in: u32',
+ '@builtin(sample_mask) sample_mask_in: u32'
+ );
+ }
+
+ const descriptor = t.getDescriptorWithStates(
+ t.getVertexStateWithOutputs(outputs),
+ t.getFragmentStateWithInputs(inputs, true)
+ );
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js
new file mode 100644
index 0000000000..390fb9f6fe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/misc.spec.js
@@ -0,0 +1,90 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+misc createRenderPipeline and createRenderPipelineAsync validation tests.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kDefaultVertexShaderCode, kDefaultFragmentShaderCode } from '../../../util/shader.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('basic')
+ .desc(`Test basic usage of createRenderPipeline.`)
+ .params(u => u.combine('isAsync', [false, true]))
+ .fn(async t => {
+ const { isAsync } = t.params;
+ const descriptor = t.getDescriptor();
+
+ t.doCreateRenderPipelineTest(isAsync, true, descriptor);
+ });
+
+g.test('vertex_state_only')
+ .desc(
+ `Tests creating vertex-state-only render pipeline. A vertex-only render pipeline has no fragment
+state (and thus has no color state), and can be created with or without depth stencil state.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .beginSubcases()
+ .combine('depthStencilFormat', ['depth24plus', 'depth24plus-stencil8', 'depth32float', ''])
+ .combine('hasColor', [false, true])
+ )
+ .fn(async t => {
+ const { isAsync, depthStencilFormat, hasColor } = t.params;
+
+ let depthStencilState;
+ if (depthStencilFormat === '') {
+ depthStencilState = undefined;
+ } else {
+ depthStencilState = { format: depthStencilFormat };
+ }
+
+ // Having targets or not should have no effect in result, since it will not appear in the
+ // descriptor in vertex-only render pipeline
+ const descriptor = t.getDescriptor({
+ noFragment: true,
+ depthStencil: depthStencilState,
+ targets: hasColor ? [{ format: 'rgba8unorm' }] : [],
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, true, descriptor);
+ });
+
+g.test('pipeline_layout,device_mismatch')
+ .desc(
+ 'Tests createRenderPipeline(Async) cannot be called with a pipeline layout created from another device'
+ )
+ .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false]))
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { isAsync, mismatched } = t.params;
+
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const layout = sourceDevice.createPipelineLayout({ bindGroupLayouts: [] });
+
+ const format = 'rgba8unorm';
+ const descriptor = {
+ layout,
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kDefaultVertexShaderCode,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: kDefaultFragmentShaderCode,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ };
+
+ t.doCreateRenderPipelineTest(isAsync, !mismatched, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/multisample_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/multisample_state.spec.js
new file mode 100644
index 0000000000..739f110d4e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/multisample_state.spec.js
@@ -0,0 +1,84 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of GPUMultisampleState of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kDefaultFragmentShaderCode } from '../../../util/shader.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('count')
+ .desc(`If multisample.count must either be 1 or 4.`)
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .beginSubcases()
+ .combine('count', [0, 1, 2, 3, 4, 8, 16, 1024])
+ )
+ .fn(async t => {
+ const { isAsync, count } = t.params;
+
+ const descriptor = t.getDescriptor({ multisample: { count, alphaToCoverageEnabled: false } });
+
+ const _success = count === 1 || count === 4;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('alpha_to_coverage,count')
+ .desc(
+ `If multisample.alphaToCoverageEnabled is true, multisample.count must be greater than 1, e.g. it can only be 4.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('alphaToCoverageEnabled', [false, true])
+ .beginSubcases()
+ .combine('count', [1, 4])
+ )
+ .fn(async t => {
+ const { isAsync, alphaToCoverageEnabled, count } = t.params;
+
+ const descriptor = t.getDescriptor({ multisample: { count, alphaToCoverageEnabled } });
+
+ const _success = alphaToCoverageEnabled ? count === 4 : count === 1 || count === 4;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('alpha_to_coverage,sample_mask')
+ .desc(
+ `If sample_mask builtin is a pipeline output of fragment, multisample.alphaToCoverageEnabled should be false.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('alphaToCoverageEnabled', [false, true])
+ .beginSubcases()
+ .combine('hasSampleMaskOutput', [false, true])
+ )
+ .fn(async t => {
+ const { isAsync, alphaToCoverageEnabled, hasSampleMaskOutput } = t.params;
+
+ const descriptor = t.getDescriptor({
+ multisample: { alphaToCoverageEnabled, count: 4 },
+ fragmentShaderCode: hasSampleMaskOutput
+ ? `
+ struct Output {
+ @builtin(sample_mask) mask_out: u32,
+ @location(0) color : vec4<f32>,
+ }
+ @fragment fn main() -> Output {
+ var o: Output;
+ // We need to make sure this sample_mask isn't optimized out even its value equals "no op".
+ o.mask_out = 0xFFFFFFFFu;
+ o.color = vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ return o;
+ }`
+ : kDefaultFragmentShaderCode,
+ });
+
+ const _success = !hasSampleMaskOutput || !alphaToCoverageEnabled;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/overrides.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/overrides.spec.js
new file mode 100644
index 0000000000..621ba68962
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/overrides.spec.js
@@ -0,0 +1,502 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of pipeline overridable constants of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kValue } from '../../../util/constants.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('identifier,vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for overridable constants identifiers in vertex state.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { vertexConstants: {}, _success: true },
+ { vertexConstants: { x: 1, y: 1 }, _success: true },
+ { vertexConstants: { x: 1, y: 1, 1: 1, 1000: 1 }, _success: true },
+ { vertexConstants: { xxx: 1 }, _success: false },
+ { vertexConstants: { 1: 1 }, _success: true },
+ { vertexConstants: { 2: 1 }, _success: false },
+ { vertexConstants: { z: 1 }, _success: false }, // pipeline constant id is specified for z
+ { vertexConstants: { w: 1 }, _success: false }, // pipeline constant id is specified for w
+ { vertexConstants: { 1: 1, z: 1 }, _success: false }, // pipeline constant id is specified for z
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, vertexConstants, _success } = t.params;
+
+ t.doCreateRenderPipelineTest(isAsync, _success, {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ override x: f32 = 0.0;
+ override y: f32 = 0.0;
+ @id(1) override z: f32 = 0.0;
+ @id(1000) override w: f32 = 1.0;
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(x, y, z, w);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+
+g.test('identifier,fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for overridable constants identifiers in fragment state.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { fragmentConstants: {}, _success: true },
+ { fragmentConstants: { r: 1, g: 1 }, _success: true },
+ { fragmentConstants: { r: 1, g: 1, 1: 1, 1000: 1 }, _success: true },
+ { fragmentConstants: { xxx: 1 }, _success: false },
+ { fragmentConstants: { 1: 1 }, _success: true },
+ { fragmentConstants: { 2: 1 }, _success: false },
+ { fragmentConstants: { b: 1 }, _success: false }, // pipeline constant id is specified for b
+ { fragmentConstants: { a: 1 }, _success: false }, // pipeline constant id is specified for a
+ { fragmentConstants: { 1: 1, b: 1 }, _success: false }, // pipeline constant id is specified for b
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, fragmentConstants, _success } = t.params;
+
+ const descriptor = t.getDescriptor({
+ fragmentShaderCode: `
+ override r: f32 = 0.0;
+ override g: f32 = 0.0;
+ @id(1) override b: f32 = 0.0;
+ @id(1000) override a: f32 = 0.0;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ return vec4<f32>(r, g, b, a);
+ }`,
+ fragmentConstants,
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('uninitialized,vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for uninitialized overridable constants in vertex state.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { vertexConstants: {}, _success: false },
+ { vertexConstants: { x: 1, y: 1 }, _success: false }, // z is missing
+ { vertexConstants: { x: 1, z: 1 }, _success: true },
+ { vertexConstants: { x: 1, y: 1, z: 1, w: 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, vertexConstants, _success } = t.params;
+
+ t.doCreateRenderPipelineTest(isAsync, _success, {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ override x: f32;
+ override y: f32 = 0.0;
+ override z: f32;
+ override w: f32 = 1.0;
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(x, y, z, w);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+
+g.test('uninitialized,fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for uninitialized overridable constants in fragment state.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { fragmentConstants: {}, _success: false },
+ { fragmentConstants: { r: 1, g: 1 }, _success: false }, // b is missing
+ { fragmentConstants: { r: 1, b: 1 }, _success: true },
+ { fragmentConstants: { r: 1, g: 1, b: 1, a: 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, fragmentConstants, _success } = t.params;
+
+ const descriptor = t.getDescriptor({
+ fragmentShaderCode: `
+ override r: f32;
+ override g: f32 = 0.0;
+ override b: f32;
+ override a: f32 = 0.0;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ return vec4<f32>(r, g, b, a);
+ }
+ `,
+ fragmentConstants,
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('value,type_error,vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for invalid constant values like inf, NaN will results in TypeError.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { vertexConstants: { cf: 1 }, _success: true }, // control
+ { vertexConstants: { cf: NaN }, _success: false },
+ { vertexConstants: { cf: Number.POSITIVE_INFINITY }, _success: false },
+ { vertexConstants: { cf: Number.NEGATIVE_INFINITY }, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, vertexConstants, _success } = t.params;
+
+ t.doCreateRenderPipelineTest(
+ isAsync,
+ _success,
+ {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ override cf: f32 = 0.0;
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ _ = cf;
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ },
+ 'TypeError'
+ );
+ });
+
+g.test('value,type_error,fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for invalid constant values like inf, NaN will results in TypeError.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { fragmentConstants: { cf: 1 }, _success: true }, // control
+ { fragmentConstants: { cf: NaN }, _success: false },
+ { fragmentConstants: { cf: Number.POSITIVE_INFINITY }, _success: false },
+ { fragmentConstants: { cf: Number.NEGATIVE_INFINITY }, _success: false },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, fragmentConstants, _success } = t.params;
+
+ const descriptor = t.getDescriptor({
+ fragmentShaderCode: `
+ override cf: f32 = 0.0;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ _ = cf;
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ }
+ `,
+ fragmentConstants,
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor, 'TypeError');
+ });
+
+g.test('value,validation_error,vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for unrepresentable constant values in vertex stage.
+
+TODO(#2060): test with last_f64_castable.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { vertexConstants: { cu: kValue.u32.min }, _success: true },
+ { vertexConstants: { cu: kValue.u32.min - 1 }, _success: false },
+ { vertexConstants: { cu: kValue.u32.max }, _success: true },
+ { vertexConstants: { cu: kValue.u32.max + 1 }, _success: false },
+ { vertexConstants: { ci: kValue.i32.negative.min }, _success: true },
+ { vertexConstants: { ci: kValue.i32.negative.min - 1 }, _success: false },
+ { vertexConstants: { ci: kValue.i32.positive.max }, _success: true },
+ { vertexConstants: { ci: kValue.i32.positive.max + 1 }, _success: false },
+ { vertexConstants: { cf: kValue.f32.negative.min }, _success: true },
+ { vertexConstants: { cf: kValue.f32.negative.first_f64_not_castable }, _success: false },
+ { vertexConstants: { cf: kValue.f32.positive.max }, _success: true },
+ { vertexConstants: { cf: kValue.f32.positive.first_f64_not_castable }, _success: false },
+ // Conversion to boolean can't fail
+ { vertexConstants: { cb: Number.MAX_VALUE }, _success: true },
+ { vertexConstants: { cb: kValue.i32.negative.min - 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, vertexConstants, _success } = t.params;
+
+ t.doCreateRenderPipelineTest(isAsync, _success, {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ override cb: bool = false;
+ override cu: u32 = 0u;
+ override ci: i32 = 0;
+ override cf: f32 = 0.0;
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ _ = cb;
+ _ = cu;
+ _ = ci;
+ _ = cf;
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+
+g.test('value,validation_error,fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for unrepresentable constant values in fragment stage.
+
+TODO(#2060): test with last_f64_castable.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { fragmentConstants: { cu: kValue.u32.min }, _success: true },
+ { fragmentConstants: { cu: kValue.u32.min - 1 }, _success: false },
+ { fragmentConstants: { cu: kValue.u32.max }, _success: true },
+ { fragmentConstants: { cu: kValue.u32.max + 1 }, _success: false },
+ { fragmentConstants: { ci: kValue.i32.negative.min }, _success: true },
+ { fragmentConstants: { ci: kValue.i32.negative.min - 1 }, _success: false },
+ { fragmentConstants: { ci: kValue.i32.positive.max }, _success: true },
+ { fragmentConstants: { ci: kValue.i32.positive.max + 1 }, _success: false },
+ { fragmentConstants: { cf: kValue.f32.negative.min }, _success: true },
+ { fragmentConstants: { cf: kValue.f32.negative.first_f64_not_castable }, _success: false },
+ { fragmentConstants: { cf: kValue.f32.positive.max }, _success: true },
+ { fragmentConstants: { cf: kValue.f32.positive.first_f64_not_castable }, _success: false },
+ // Conversion to boolean can't fail
+ { fragmentConstants: { cb: Number.MAX_VALUE }, _success: true },
+ { fragmentConstants: { cb: kValue.i32.negative.min - 1 }, _success: true },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, fragmentConstants, _success } = t.params;
+
+ const descriptor = t.getDescriptor({
+ fragmentShaderCode: `
+ override cb: bool = false;
+ override cu: u32 = 0u;
+ override ci: i32 = 0;
+ override cf: f32 = 0.0;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ _ = cb;
+ _ = cu;
+ _ = ci;
+ _ = cf;
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ }
+ `,
+ fragmentConstants,
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('value,validation_error,f16,vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for unrepresentable f16 constant values in vertex stage.
+
+TODO(#2060): Tighten the cases around the valid/invalid boundary once we have WGSL spec
+clarity on whether values like f16.positive.last_f64_castable would be valid. See issue.
+`
+ )
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { vertexConstants: { cf16: kValue.f16.negative.min }, _success: true },
+ { vertexConstants: { cf16: kValue.f16.negative.first_f64_not_castable }, _success: false },
+ { vertexConstants: { cf16: kValue.f16.positive.max }, _success: true },
+ { vertexConstants: { cf16: kValue.f16.positive.first_f64_not_castable }, _success: false },
+ { vertexConstants: { cf16: kValue.f32.negative.min }, _success: false },
+ { vertexConstants: { cf16: kValue.f32.positive.max }, _success: false },
+ { vertexConstants: { cf16: kValue.f32.negative.first_f64_not_castable }, _success: false },
+ { vertexConstants: { cf16: kValue.f32.positive.first_f64_not_castable }, _success: false },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
+ })
+ .fn(async t => {
+ const { isAsync, vertexConstants, _success } = t.params;
+
+ t.doCreateRenderPipelineTest(isAsync, _success, {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ enable f16;
+
+ override cf16: f16 = 0.0h;
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ _ = cf16;
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ constants: vertexConstants,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+
+g.test('value,validation_error,f16,fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) validation for unrepresentable f16 constant values in fragment stage.
+
+TODO(#2060): Tighten the cases around the valid/invalid boundary once we have WGSL spec
+clarity on whether values like f16.positive.last_f64_castable would be valid. See issue.
+`
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
+ })
+ .params(u =>
+ u //
+ .combine('isAsync', [true, false])
+ .combineWithParams([
+ { fragmentConstants: { cf16: kValue.f16.negative.min }, _success: true },
+ {
+ fragmentConstants: { cf16: kValue.f16.negative.first_f64_not_castable },
+ _success: false,
+ },
+ { fragmentConstants: { cf16: kValue.f16.positive.max }, _success: true },
+ {
+ fragmentConstants: { cf16: kValue.f16.positive.first_f64_not_castable },
+ _success: false,
+ },
+ { fragmentConstants: { cf16: kValue.f32.negative.min }, _success: false },
+ { fragmentConstants: { cf16: kValue.f32.positive.max }, _success: false },
+ {
+ fragmentConstants: { cf16: kValue.f32.negative.first_f64_not_castable },
+ _success: false,
+ },
+ {
+ fragmentConstants: { cf16: kValue.f32.positive.first_f64_not_castable },
+ _success: false,
+ },
+ ])
+ )
+ .fn(async t => {
+ const { isAsync, fragmentConstants, _success } = t.params;
+
+ const descriptor = t.getDescriptor({
+ fragmentShaderCode: `
+ enable f16;
+
+ override cf16: f16 = 0.0h;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ _ = cf16;
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+ }
+ `,
+ fragmentConstants,
+ });
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/primitive_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/primitive_state.spec.js
new file mode 100644
index 0000000000..025ff1755b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/primitive_state.spec.js
@@ -0,0 +1,43 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of GPUPrimitiveState of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kPrimitiveTopology, kIndexFormat } from '../../../capability_info.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('strip_index_format')
+ .desc(
+ `If primitive.topology is not "line-strip" or "triangle-strip", primitive.stripIndexFormat must be undefined.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('topology', [undefined, ...kPrimitiveTopology])
+ .combine('stripIndexFormat', [undefined, ...kIndexFormat])
+ )
+ .fn(async t => {
+ const { isAsync, topology, stripIndexFormat } = t.params;
+
+ const descriptor = t.getDescriptor({ primitive: { topology, stripIndexFormat } });
+
+ const _success =
+ topology === 'line-strip' || topology === 'triangle-strip' || stripIndexFormat === undefined;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('unclipped_depth')
+ .desc(`If primitive.unclippedDepth is true, features must contain "depth-clip-control".`)
+ .params(u => u.combine('isAsync', [false, true]).combine('unclippedDepth', [false, true]))
+ .fn(async t => {
+ const { isAsync, unclippedDepth } = t.params;
+
+ const descriptor = t.getDescriptor({ primitive: { unclippedDepth } });
+
+ const _success = !unclippedDepth || t.device.features.has('depth-clip-control');
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/shader_module.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/shader_module.spec.js
new file mode 100644
index 0000000000..93970613ce
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/shader_module.spec.js
@@ -0,0 +1,113 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests createRenderPipeline validation issues related to the shader modules.
+
+Note: entry point matching tests are in ../shader_module/entry_point.spec.ts
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ getFragmentShaderCodeWithOutput,
+ kDefaultVertexShaderCode,
+ kDefaultFragmentShaderCode,
+} from '../../../util/shader.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+const values = [0, 1, 0, 1];
+
+g.test('device_mismatch')
+ .desc(
+ 'Tests createRenderPipeline(Async) cannot be called with a shader module created from another device'
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('isAsync', [true, false]).combineWithParams([
+ { vertex_mismatched: false, fragment_mismatched: false, _success: true },
+ { vertex_mismatched: true, fragment_mismatched: false, _success: false },
+ { vertex_mismatched: false, fragment_mismatched: true, _success: false },
+ ])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { isAsync, vertex_mismatched, fragment_mismatched, _success } = t.params;
+
+ const code = `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }
+ `;
+
+ const descriptor = {
+ vertex: {
+ module: vertex_mismatched
+ ? t.mismatchedDevice.createShaderModule({ code })
+ : t.device.createShaderModule({ code }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: fragment_mismatched
+ ? t.mismatchedDevice.createShaderModule({
+ code: getFragmentShaderCodeWithOutput([
+ { values, plainType: 'f32', componentCount: 4 },
+ ]),
+ })
+ : t.device.createShaderModule({
+ code: getFragmentShaderCodeWithOutput([
+ { values, plainType: 'f32', componentCount: 4 },
+ ]),
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ layout: t.getPipelineLayout(),
+ };
+
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('invalid,vertex')
+ .desc(`Tests shader module must be valid.`)
+ .params(u => u.combine('isAsync', [true, false]).combine('isVertexShaderValid', [true, false]))
+ .fn(async t => {
+ const { isAsync, isVertexShaderValid } = t.params;
+ t.doCreateRenderPipelineTest(isAsync, isVertexShaderValid, {
+ layout: 'auto',
+ vertex: {
+ module: isVertexShaderValid
+ ? t.device.createShaderModule({
+ code: kDefaultVertexShaderCode,
+ })
+ : t.createInvalidShaderModule(),
+ entryPoint: 'main',
+ },
+ });
+ });
+
+g.test('invalid,fragment')
+ .desc(`Tests shader module must be valid.`)
+ .params(u => u.combine('isAsync', [true, false]).combine('isFragmentShaderValid', [true, false]))
+ .fn(async t => {
+ const { isAsync, isFragmentShaderValid } = t.params;
+ t.doCreateRenderPipelineTest(isAsync, isFragmentShaderValid, {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kDefaultVertexShaderCode,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: isFragmentShaderValid
+ ? t.device.createShaderModule({
+ code: kDefaultFragmentShaderCode,
+ })
+ : t.createInvalidShaderModule(),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/vertex_state.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/vertex_state.spec.js
new file mode 100644
index 0000000000..dbca213028
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/render_pipeline/vertex_state.spec.js
@@ -0,0 +1,639 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This test dedicatedly tests validation of GPUVertexState of createRenderPipeline.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kMaxVertexAttributes,
+ kMaxVertexBufferArrayStride,
+ kMaxVertexBuffers,
+ kVertexFormats,
+ kVertexFormatInfo,
+} from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+const VERTEX_SHADER_CODE_WITH_NO_INPUT = `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 0.0);
+ }
+`;
+
+function addTestAttributes(
+ attributes,
+ {
+ testAttribute,
+ testAttributeAtStart = true,
+ extraAttributeCount = 0,
+ extraAttributeSkippedLocations = [],
+ }
+) {
+ // Add a bunch of dummy attributes each with a different location such that none of the locations
+ // are in extraAttributeSkippedLocations
+ let currentLocation = 0;
+ let extraAttribsAdded = 0;
+ while (extraAttribsAdded !== extraAttributeCount) {
+ if (extraAttributeSkippedLocations.includes(currentLocation)) {
+ currentLocation++;
+ continue;
+ }
+
+ attributes.push({ format: 'float32', shaderLocation: currentLocation, offset: 0 });
+ currentLocation++;
+ extraAttribsAdded++;
+ }
+
+ // Add the test attribute at the start or the end of the attributes.
+ if (testAttribute) {
+ if (testAttributeAtStart) {
+ attributes.unshift(testAttribute);
+ } else {
+ attributes.push(testAttribute);
+ }
+ }
+}
+
+class F extends ValidationTest {
+ getDescriptor(buffers, vertexShaderCode) {
+ const descriptor = {
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({ code: vertexShaderCode }),
+ entryPoint: 'main',
+ buffers,
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ };
+ return descriptor;
+ }
+
+ testVertexState(success, buffers, vertexShader = VERTEX_SHADER_CODE_WITH_NO_INPUT) {
+ const vsModule = this.device.createShaderModule({ code: vertexShader });
+ const fsModule = this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ });
+
+ this.expectValidationError(() => {
+ this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: vsModule,
+ entryPoint: 'main',
+ buffers,
+ },
+ fragment: {
+ module: fsModule,
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ }, !success);
+ }
+
+ generateTestVertexShader(inputs) {
+ let interfaces = '';
+ let body = '';
+
+ let count = 0;
+ for (const input of inputs) {
+ interfaces += `@location(${input.location}) input${count} : ${input.type},\n`;
+ body += `var i${count} : ${input.type} = input.input${count};\n`;
+ count++;
+ }
+
+ return `
+ struct Inputs {
+ ${interfaces}
+ };
+ @vertex fn main(input : Inputs) -> @builtin(position) vec4<f32> {
+ ${body}
+ return vec4<f32>(0.0, 0.0, 0.0, 0.0);
+ }
+ `;
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('max_vertex_buffer_limit')
+ .desc(
+ `Test that only up to <maxVertexBuffers> vertex buffers are allowed.
+ - Tests with 0, 1, limits, limits + 1 vertex buffers.
+ - Tests with the last buffer having an attribute or not.
+ This also happens to test that vertex buffers with no attributes are allowed and that a vertex state with no buffers is allowed.`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('count', [0, 1, kMaxVertexBuffers, kMaxVertexBuffers + 1])
+ .combine('lastEmpty', [false, true])
+ )
+ .fn(t => {
+ const { count, lastEmpty } = t.params;
+
+ const vertexBuffers = [];
+ for (let i = 0; i < count; i++) {
+ if (lastEmpty || i !== count - 1) {
+ vertexBuffers.push({ attributes: [], arrayStride: 0 });
+ } else {
+ vertexBuffers.push({
+ attributes: [{ format: 'float32', offset: 0, shaderLocation: 0 }],
+ arrayStride: 0,
+ });
+ }
+ }
+
+ const success = count <= kMaxVertexBuffers;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('max_vertex_attribute_limit')
+ .desc(
+ `Test that only up to <maxVertexAttributes> vertex attributes are allowed.
+ - Tests with 0, 1, limit, limits + 1 vertex attribute.
+ - Tests with 0, 1, 4 attributes per buffer (with remaining attributes in the last buffer).`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('attribCount', [0, 1, kMaxVertexAttributes, kMaxVertexAttributes + 1])
+ .combine('attribsPerBuffer', [0, 1, 4])
+ )
+ .fn(t => {
+ const { attribCount, attribsPerBuffer } = t.params;
+
+ const vertexBuffers = [];
+
+ let attribsAdded = 0;
+ while (attribsAdded !== attribCount) {
+ // Choose how many attributes to add for this buffer. The last buffer gets all remaining attributes.
+ let targetCount = Math.min(attribCount, attribsAdded + attribsPerBuffer);
+ if (vertexBuffers.length === kMaxVertexBuffers - 1) {
+ targetCount = attribCount;
+ }
+
+ const attributes = [];
+ while (attribsAdded !== targetCount) {
+ attributes.push({ format: 'float32', offset: 0, shaderLocation: attribsAdded });
+ attribsAdded++;
+ }
+
+ vertexBuffers.push({ arrayStride: 0, attributes });
+ }
+
+ const success = attribCount <= kMaxVertexAttributes;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('max_vertex_buffer_array_stride_limit')
+ .desc(
+ `Test that the vertex buffer arrayStride must be at most <maxVertexBufferArrayStride>.
+ - Test for various vertex buffer indices
+ - Test for array strides 0, 4, 256, limit - 4, limit, limit + 4`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('arrayStride', [
+ 0,
+ 4,
+ 256,
+ kMaxVertexBufferArrayStride - 4,
+ kMaxVertexBufferArrayStride,
+ kMaxVertexBufferArrayStride + 4,
+ ])
+ )
+ .fn(t => {
+ const { vertexBufferIndex, arrayStride } = t.params;
+
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride, attributes: [] };
+
+ const success = arrayStride <= kMaxVertexBufferArrayStride;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('vertex_buffer_array_stride_limit_alignment')
+ .desc(
+ `Test that the vertex buffer arrayStride must be a multiple of 4 (including 0).
+ - Test for various vertex buffer indices
+ - Test for array strides 0, 1, 2, 4, limit - 4, limit - 2, limit`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('arrayStride', [
+ 0,
+ 1,
+ 2,
+ 4,
+ kMaxVertexBufferArrayStride - 4,
+ kMaxVertexBufferArrayStride - 2,
+ kMaxVertexBufferArrayStride,
+ ])
+ )
+ .fn(t => {
+ const { vertexBufferIndex, arrayStride } = t.params;
+
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride, attributes: [] };
+
+ const success = arrayStride % 4 === 0;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('vertex_attribute_shaderLocation_limit')
+ .desc(
+ `Test shaderLocation must be less than maxVertexAttributes.
+ - Test for various vertex buffer indices
+ - Test for various amounts of attributes in that vertex buffer
+ - Test for shaderLocation 0, 1, limit - 1, limit`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('extraAttributeCount', [0, 1, kMaxVertexAttributes - 1])
+ .combine('testAttributeAtStart', [false, true])
+ .combine('testShaderLocation', [0, 1, kMaxVertexAttributes - 1, kMaxVertexAttributes])
+ )
+ .fn(t => {
+ const {
+ vertexBufferIndex,
+ extraAttributeCount,
+ testShaderLocation,
+ testAttributeAtStart,
+ } = t.params;
+
+ const attributes = [];
+ addTestAttributes(attributes, {
+ testAttribute: { format: 'float32', offset: 0, shaderLocation: testShaderLocation },
+ testAttributeAtStart,
+ extraAttributeCount,
+ extraAttributeSkippedLocations: [testShaderLocation],
+ });
+
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride: 256, attributes };
+
+ const success = testShaderLocation < kMaxVertexAttributes;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('vertex_attribute_shaderLocation_unique')
+ .desc(
+ `Test that shaderLocation must be unique in the vertex state.
+ - Test for various pairs of buffers that contain the potentially conflicting attributes
+ - Test for the potentially conflicting attributes in various places in the buffers (with dummy attributes)
+ - Test for various shaderLocations that conflict or not`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('vertexBufferIndexA', [0, 1, kMaxVertexBuffers - 1])
+ .combine('vertexBufferIndexB', [0, 1, kMaxVertexBuffers - 1])
+ .combine('testAttributeAtStartA', [false, true])
+ .combine('testAttributeAtStartB', [false, true])
+ .combine('shaderLocationA', [0, 1, 7, kMaxVertexAttributes - 1])
+ .combine('shaderLocationB', [0, 1, 7, kMaxVertexAttributes - 1])
+ .combine('extraAttributeCount', [0, 4])
+ )
+ .fn(t => {
+ const {
+ vertexBufferIndexA,
+ vertexBufferIndexB,
+ testAttributeAtStartA,
+ testAttributeAtStartB,
+ shaderLocationA,
+ shaderLocationB,
+ extraAttributeCount,
+ } = t.params;
+
+ // Depending on the params, the vertexBuffer for A and B can be the same or different. To support
+ // both cases without code changes we treat `vertexBufferAttributes` as a map from indices to
+ // vertex buffer descriptors, with A and B potentially reusing the same JS object if they have the
+ // same index.
+ const vertexBufferAttributes = [];
+ vertexBufferAttributes[vertexBufferIndexA] = [];
+ vertexBufferAttributes[vertexBufferIndexB] = [];
+
+ // Add the dummy attributes for attribute A
+ const attributesA = vertexBufferAttributes[vertexBufferIndexA];
+ addTestAttributes(attributesA, {
+ testAttribute: { format: 'float32', offset: 0, shaderLocation: shaderLocationA },
+ testAttributeAtStart: testAttributeAtStartA,
+ extraAttributeCount,
+ extraAttributeSkippedLocations: [shaderLocationA, shaderLocationB],
+ });
+
+ // Add attribute B. Not that attributesB can be the same object as attributesA so they end
+ // up in the same vertex buffer.
+ const attributesB = vertexBufferAttributes[vertexBufferIndexB];
+ addTestAttributes(attributesB, {
+ testAttribute: { format: 'float32', offset: 0, shaderLocation: shaderLocationB },
+ testAttributeAtStart: testAttributeAtStartB,
+ });
+
+ // Use the attributes to make the list of vertex buffers. Note that we might be setting the same vertex
+ // buffer twice, but that only happens when it is the only vertex buffer.
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndexA] = { arrayStride: 256, attributes: attributesA };
+ vertexBuffers[vertexBufferIndexB] = { arrayStride: 256, attributes: attributesB };
+
+ // Note that an empty vertex shader will be used so errors only happens because of the conflict
+ // in the vertex state.
+ const success = shaderLocationA !== shaderLocationB;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('vertex_shader_input_location_limit')
+ .desc(
+ `Test that vertex shader's input's location decoration must be less than maxVertexAttributes.
+ - Test for shaderLocation 0, 1, limit - 1, limit, MAX_I32 (the WGSL spec requires a non-negative i32)`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('testLocation', [0, 1, kMaxVertexAttributes - 1, kMaxVertexAttributes, 2 ** 31 - 1])
+ )
+ .fn(t => {
+ const { testLocation } = t.params;
+
+ const shader = t.generateTestVertexShader([
+ {
+ type: 'vec4<f32>',
+ location: testLocation,
+ },
+ ]);
+
+ const vertexBuffers = [
+ {
+ arrayStride: 512,
+ attributes: [
+ {
+ format: 'float32',
+ offset: 0,
+ shaderLocation: testLocation,
+ },
+ ],
+ },
+ ];
+
+ const success = testLocation < kMaxVertexAttributes;
+ t.testVertexState(success, vertexBuffers, shader);
+ });
+
+g.test('vertex_shader_input_location_in_vertex_state')
+ .desc(
+ `Test that a vertex shader defined in the shader must have a corresponding attribute in the vertex state.
+ - Test for various input locations.
+ - Test for the attribute in various places in the list of vertex buffer and various places inside the vertex buffer descriptor`
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('extraAttributeCount', [0, 1, kMaxVertexAttributes - 1])
+ .combine('testAttributeAtStart', [false, true])
+ .combine('testShaderLocation', [0, 1, 4, 7, kMaxVertexAttributes - 1])
+ )
+ .fn(t => {
+ const {
+ vertexBufferIndex,
+ extraAttributeCount,
+ testAttributeAtStart,
+ testShaderLocation,
+ } = t.params;
+ // We have a shader using `testShaderLocation`.
+ const shader = t.generateTestVertexShader([
+ {
+ type: 'vec4<f32>',
+ location: testShaderLocation,
+ },
+ ]);
+
+ const attributes = [];
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride: 256, attributes };
+
+ // Fill attributes with a bunch of attributes for other locations.
+ // Using that vertex state is invalid because the vertex state doesn't contain the test location
+ addTestAttributes(attributes, {
+ extraAttributeCount,
+ extraAttributeSkippedLocations: [testShaderLocation],
+ });
+ t.testVertexState(false, vertexBuffers, shader);
+
+ // Add an attribute for the test location and try again.
+ addTestAttributes(attributes, {
+ testAttribute: { format: 'float32', shaderLocation: testShaderLocation, offset: 0 },
+ testAttributeAtStart,
+ });
+ t.testVertexState(true, vertexBuffers, shader);
+ });
+
+g.test('vertex_shader_type_matches_attribute_format')
+ .desc(
+ `
+ Test that the vertex shader declaration must have a type compatible with the vertex format.
+ - Test for all formats.
+ - Test for all combinations of u/i/f32 with and without vectors.`
+ )
+ .params(u =>
+ u
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('shaderBaseType', ['u32', 'i32', 'f32'])
+ .expand('shaderType', p => [
+ p.shaderBaseType,
+ `vec2<${p.shaderBaseType}>`,
+ `vec3<${p.shaderBaseType}>`,
+ `vec4<${p.shaderBaseType}>`,
+ ])
+ )
+ .fn(t => {
+ const { format, shaderBaseType, shaderType } = t.params;
+ const shader = t.generateTestVertexShader([
+ {
+ type: shaderType,
+ location: 0,
+ },
+ ]);
+
+ const requiredBaseType = {
+ sint: 'i32',
+ uint: 'u32',
+ snorm: 'f32',
+ unorm: 'f32',
+ float: 'f32',
+ }[kVertexFormatInfo[format].type];
+
+ const success = requiredBaseType === shaderBaseType;
+ t.testVertexState(
+ success,
+ [
+ {
+ arrayStride: 0,
+ attributes: [{ offset: 0, shaderLocation: 0, format }],
+ },
+ ],
+
+ shader
+ );
+ });
+
+g.test('vertex_attribute_offset_alignment')
+ .desc(
+ `
+ Test that vertex attribute offsets must be aligned to the format's component byte size.
+ - Test for all formats.
+ - Test for various arrayStrides and offsets within that stride
+ - Test for various vertex buffer indices
+ - Test for various amounts of attributes in that vertex buffer`
+ )
+ .params(u =>
+ u
+ .combine('format', kVertexFormats)
+ .combine('arrayStride', [256, kMaxVertexBufferArrayStride])
+ .expand('offset', p => {
+ const { bytesPerComponent, componentCount } = kVertexFormatInfo[p.format];
+ const formatSize = bytesPerComponent * componentCount;
+
+ return new Set([
+ 0,
+ Math.floor(formatSize / 2),
+ formatSize,
+ 2,
+ 4,
+ p.arrayStride - formatSize,
+ p.arrayStride - formatSize - Math.floor(formatSize / 2),
+ p.arrayStride - formatSize - 4,
+ p.arrayStride - formatSize - 2,
+ ]);
+ })
+ .beginSubcases()
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('extraAttributeCount', [0, 1, kMaxVertexAttributes - 1])
+ .combine('testAttributeAtStart', [false, true])
+ )
+ .fn(t => {
+ const {
+ format,
+ arrayStride,
+ offset,
+ vertexBufferIndex,
+ extraAttributeCount,
+ testAttributeAtStart,
+ } = t.params;
+
+ const attributes = [];
+ addTestAttributes(attributes, {
+ testAttribute: { format, offset, shaderLocation: 0 },
+ testAttributeAtStart,
+ extraAttributeCount,
+ extraAttributeSkippedLocations: [0],
+ });
+
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride, attributes };
+
+ const formatInfo = kVertexFormatInfo[format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ const success = offset % Math.min(4, formatSize) === 0;
+
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('vertex_attribute_contained_in_stride')
+ .desc(
+ `
+ Test that vertex attribute [offset, offset + formatSize) must be contained in the arrayStride if arrayStride is not 0:
+ - Test for all formats.
+ - Test for various arrayStrides and offsets within that stride
+ - Test for various vertex buffer indices
+ - Test for various amounts of attributes in that vertex buffer`
+ )
+ .params(u =>
+ u
+ .combine('format', kVertexFormats)
+ .beginSubcases()
+ .combine('arrayStride', [
+ 0,
+ 256,
+ kMaxVertexBufferArrayStride - 4,
+ kMaxVertexBufferArrayStride,
+ ])
+ .expand('offset', function* (p) {
+ // Compute a bunch of test offsets to test.
+ const { bytesPerComponent, componentCount } = kVertexFormatInfo[p.format];
+ const formatSize = bytesPerComponent * componentCount;
+ yield 0;
+ yield 4;
+
+ // arrayStride = 0 is a special case because for the offset validation it acts the same
+ // as arrayStride = kMaxVertexBufferArrayStride. We special case here so as to avoid adding
+ // negative offsets that would cause an IDL exception to be thrown instead of a validation
+ // error.
+ const stride = p.arrayStride !== 0 ? p.arrayStride : kMaxVertexBufferArrayStride;
+ yield stride - formatSize;
+ yield stride - formatSize + 4;
+
+ // Avoid adding duplicate cases when formatSize == 4 (it is already tested above)
+ if (formatSize !== 4) {
+ yield formatSize;
+ yield stride;
+ }
+ })
+ .combine('vertexBufferIndex', [0, 1, kMaxVertexBuffers - 1])
+ .combine('extraAttributeCount', [0, 1, kMaxVertexAttributes - 1])
+ .combine('testAttributeAtStart', [false, true])
+ )
+ .fn(t => {
+ const {
+ format,
+ arrayStride,
+ offset,
+ vertexBufferIndex,
+ extraAttributeCount,
+ testAttributeAtStart,
+ } = t.params;
+
+ const attributes = [];
+ addTestAttributes(attributes, {
+ testAttribute: { format, offset, shaderLocation: 0 },
+ testAttributeAtStart,
+ extraAttributeCount,
+ extraAttributeSkippedLocations: [0],
+ });
+
+ const vertexBuffers = [];
+ vertexBuffers[vertexBufferIndex] = { arrayStride, attributes };
+
+ const formatInfo = kVertexFormatInfo[format];
+ const formatSize = formatInfo.bytesPerComponent * formatInfo.componentCount;
+ const limit = arrayStride === 0 ? kMaxVertexBufferArrayStride : arrayStride;
+
+ const success = offset + formatSize <= limit;
+ t.testVertexState(success, vertexBuffers);
+ });
+
+g.test('many_attributes_overlapping')
+ .desc(`Test that it is valid to have many vertex attributes overlap`)
+ .fn(async t => {
+ // Create many attributes, each of them intersects with at least 3 others.
+ const attributes = [];
+ const formats = ['float32x4', 'uint32x4', 'sint32x4'];
+ for (let i = 0; i < kMaxVertexAttributes; i++) {
+ attributes.push({ format: formats[i % 3], offset: i * 4, shaderLocation: i });
+ }
+
+ t.testVertexState(true, [{ arrayStride: 0, attributes }]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_encoder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_encoder.spec.js
new file mode 100644
index 0000000000..a008a3f653
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_encoder.spec.js
@@ -0,0 +1,879 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Buffer Usages Validation Tests in Render Pass and Compute Pass.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../../common/util/util.js';
+import { ValidationTest } from '../../validation_test.js';
+
+const kBoundBufferSize = 256;
+
+export const kAllBufferUsages = [
+ 'uniform',
+ 'storage',
+ 'read-only-storage',
+ 'vertex',
+ 'index',
+ 'indirect',
+ 'indexedIndirect',
+];
+
+export class BufferResourceUsageTest extends ValidationTest {
+ createBindGroupLayoutForTest(type, resourceVisibility) {
+ const bindGroupLayoutEntry = {
+ binding: 0,
+ visibility:
+ resourceVisibility === 'compute' ? GPUShaderStage.COMPUTE : GPUShaderStage.FRAGMENT,
+ buffer: {
+ type,
+ },
+ };
+ return this.device.createBindGroupLayout({
+ entries: [bindGroupLayoutEntry],
+ });
+ }
+
+ createBindGroupForTest(buffer, offset, type, resourceVisibility) {
+ return this.device.createBindGroup({
+ layout: this.createBindGroupLayoutForTest(type, resourceVisibility),
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer, offset, size: kBoundBufferSize },
+ },
+ ],
+ });
+ }
+
+ beginSimpleRenderPass(encoder) {
+ const colorTexture = this.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [16, 16, 1],
+ });
+ return encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+
+ createRenderPipelineForTest(pipelineLayout, vertexBufferCount) {
+ const vertexBuffers = [];
+ for (let i = 0; i < vertexBufferCount; ++i) {
+ vertexBuffers.push({
+ arrayStride: 4,
+ attributes: [
+ {
+ format: 'float32',
+ shaderLocation: i,
+ offset: 0,
+ },
+ ],
+ });
+ }
+
+ return this.device.createRenderPipeline({
+ layout: pipelineLayout,
+ vertex: {
+ module: this.device.createShaderModule({
+ code: this.getNoOpShaderCode('VERTEX'),
+ }),
+ entryPoint: 'main',
+ buffers: vertexBuffers,
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ }
+}
+
+function IsBufferUsageInBindGroup(bufferUsage) {
+ switch (bufferUsage) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage':
+ return true;
+ case 'vertex':
+ case 'index':
+ case 'indirect':
+ case 'indexedIndirect':
+ return false;
+ default:
+ unreachable();
+ }
+}
+
+export const g = makeTestGroup(BufferResourceUsageTest);
+
+g.test('subresources,buffer_usage_in_one_compute_pass_with_no_dispatch')
+ .desc(
+ `
+Test that it is always allowed to set multiple bind groups with same buffer in a compute pass
+encoder without any dispatch calls as state-setting compute pass commands, like setBindGroup(index,
+bindGroup, dynamicOffsets), do not contribute directly to a usage scope.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage'])
+ .combine('usage1', ['uniform', 'storage', 'read-only-storage'])
+ .beginSubcases()
+ .combine('visibility0', ['compute', 'fragment'])
+ .combine('visibility1', ['compute', 'fragment'])
+ .combine('hasOverlap', [true, false])
+ )
+ .fn(async t => {
+ const { usage0, usage1, visibility0, visibility1, hasOverlap } = t.params;
+
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const computePassEncoder = encoder.beginComputePass();
+
+ const offset0 = 0;
+ const bindGroup0 = t.createBindGroupForTest(buffer, offset0, usage0, visibility0);
+ computePassEncoder.setBindGroup(0, bindGroup0);
+
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ const bindGroup1 = t.createBindGroupForTest(buffer, offset1, usage1, visibility1);
+ computePassEncoder.setBindGroup(1, bindGroup1);
+
+ computePassEncoder.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
+
+g.test('subresources,buffer_usage_in_one_compute_pass_with_one_dispatch')
+ .desc(
+ `
+Test that when one buffer is used in one compute pass encoder, its list of internal usages within
+one usage scope can only be a compatible usage list. According to WebGPU SPEC, within one dispatch,
+for each bind group slot that is used by the current GPUComputePipeline's layout, every subresource
+referenced by that bind group is "used" in the usage scope. `
+ )
+ .params(u =>
+ u
+ .combine('usage0AccessibleInDispatch', [true, false])
+ .combine('usage1AccessibleInDispatch', [true, false])
+ .combine('dispatchBeforeUsage1', [true, false])
+ .beginSubcases()
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage', 'indirect'])
+ .combine('visibility0', ['compute', 'fragment'])
+ .filter(t => {
+ // The buffer with `indirect` usage is always accessible in the dispatch call.
+ if (
+ t.usage0 === 'indirect' &&
+ (!t.usage0AccessibleInDispatch || t.visibility0 !== 'compute' || !t.dispatchBeforeUsage1)
+ ) {
+ return false;
+ }
+ if (t.usage0AccessibleInDispatch && t.visibility0 !== 'compute') {
+ return false;
+ }
+ if (t.dispatchBeforeUsage1 && t.usage1AccessibleInDispatch) {
+ return false;
+ }
+ return true;
+ })
+ .combine('usage1', ['uniform', 'storage', 'read-only-storage', 'indirect'])
+ .combine('visibility1', ['compute', 'fragment'])
+ .filter(t => {
+ if (
+ t.usage1 === 'indirect' &&
+ (!t.usage1AccessibleInDispatch || t.visibility1 !== 'compute' || t.dispatchBeforeUsage1)
+ ) {
+ return false;
+ }
+ // When the first buffer usage is `indirect`, there has already been one dispatch call, so
+ // in this test we always make the second usage inaccessible in the dispatch call.
+ if (
+ t.usage1AccessibleInDispatch &&
+ (t.visibility1 !== 'compute' || t.usage0 === 'indirect')
+ ) {
+ return false;
+ }
+ return true;
+ })
+ .combine('hasOverlap', [true, false])
+ )
+ .fn(async t => {
+ const {
+ usage0AccessibleInDispatch,
+ usage1AccessibleInDispatch,
+ dispatchBeforeUsage1,
+ usage0,
+ visibility0,
+ usage1,
+ visibility1,
+ hasOverlap,
+ } = t.params;
+
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const computePassEncoder = encoder.beginComputePass();
+
+ const offset0 = 0;
+ switch (usage0) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup0 = t.createBindGroupForTest(buffer, offset0, usage0, visibility0);
+ computePassEncoder.setBindGroup(0, bindGroup0);
+
+ /*
+ * setBindGroup(bindGroup0);
+ * dispatchWorkgroups();
+ * setBindGroup(bindGroup1);
+ */
+ if (dispatchBeforeUsage1) {
+ let pipelineLayout = undefined;
+ if (usage0AccessibleInDispatch) {
+ const bindGroupLayout0 = t.createBindGroupLayoutForTest(usage0, visibility0);
+ pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout0],
+ });
+ }
+ const computePipeline = t.createNoOpComputePipeline(pipelineLayout);
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroups(1);
+ }
+ break;
+ }
+ case 'indirect': {
+ /*
+ * dispatchWorkgroupsIndirect(buffer);
+ * setBindGroup(bindGroup1);
+ */
+ assert(dispatchBeforeUsage1);
+ const computePipeline = t.createNoOpComputePipeline();
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroupsIndirect(buffer, offset0);
+ break;
+ }
+ }
+
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ switch (usage1) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup1 = t.createBindGroupForTest(buffer, offset1, usage1, visibility1);
+ const bindGroupIndex = usage0AccessibleInDispatch ? 1 : 0;
+ computePassEncoder.setBindGroup(bindGroupIndex, bindGroup1);
+
+ /*
+ * setBindGroup(bindGroup0);
+ * setBindGroup(bindGroup1);
+ * dispatchWorkgroups();
+ */
+ if (!dispatchBeforeUsage1) {
+ const bindGroupLayouts = [];
+ if (usage0AccessibleInDispatch && usage0 !== 'indirect') {
+ const bindGroupLayout0 = t.createBindGroupLayoutForTest(usage0, visibility0);
+ bindGroupLayouts.push(bindGroupLayout0);
+ }
+ if (usage1AccessibleInDispatch) {
+ const bindGroupLayout1 = t.createBindGroupLayoutForTest(usage1, visibility1);
+ bindGroupLayouts.push(bindGroupLayout1);
+ }
+ const pipelineLayout = bindGroupLayouts
+ ? t.device.createPipelineLayout({
+ bindGroupLayouts,
+ })
+ : undefined;
+ const computePipeline = t.createNoOpComputePipeline(pipelineLayout);
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroups(1);
+ }
+ break;
+ }
+ case 'indirect': {
+ /*
+ * setBindGroup(bindGroup0);
+ * dispatchWorkgroupsIndirect(buffer);
+ */
+ assert(!dispatchBeforeUsage1);
+ let pipelineLayout = undefined;
+ if (usage0AccessibleInDispatch) {
+ assert(usage0 !== 'indirect');
+ pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [t.createBindGroupLayoutForTest(usage0, visibility0)],
+ });
+ }
+ const computePipeline = t.createNoOpComputePipeline(pipelineLayout);
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroupsIndirect(buffer, offset1);
+ break;
+ }
+ }
+
+ computePassEncoder.end();
+
+ const usageHasConflict =
+ (usage0 === 'storage' && usage1 !== 'storage') ||
+ (usage0 !== 'storage' && usage1 === 'storage');
+ const fail =
+ usageHasConflict &&
+ visibility0 === 'compute' &&
+ visibility1 === 'compute' &&
+ usage0AccessibleInDispatch &&
+ usage1AccessibleInDispatch;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, fail);
+ });
+
+g.test('subresources,buffer_usage_in_compute_pass_with_two_dispatches')
+ .desc(
+ `
+Test that it is always allowed to use one buffer in different dispatch calls as in WebGPU SPEC,
+within one dispatch, for each bind group slot that is used by the current GPUComputePipeline's
+layout, every subresource referenced by that bind group is "used" in the usage scope, and different
+dispatch calls refer to different usage scopes.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage', 'indirect'])
+ .combine('usage1', ['uniform', 'storage', 'read-only-storage', 'indirect'])
+ .beginSubcases()
+ .combine('inSamePass', [true, false])
+ .combine('hasOverlap', [true, false])
+ )
+ .fn(async t => {
+ const { usage0, usage1, inSamePass, hasOverlap } = t.params;
+
+ const UseBufferOnComputePassEncoder = (computePassEncoder, buffer, usage, offset) => {
+ switch (usage) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup = t.createBindGroupForTest(buffer, offset, usage, 'compute');
+ computePassEncoder.setBindGroup(0, bindGroup);
+
+ const bindGroupLayout = t.createBindGroupLayoutForTest(usage, 'compute');
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ });
+ const computePipeline = t.createNoOpComputePipeline(pipelineLayout);
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroups(1);
+ break;
+ }
+ case 'indirect': {
+ const computePipeline = t.createNoOpComputePipeline();
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroupsIndirect(buffer, offset);
+ break;
+ }
+ default:
+ unreachable();
+ break;
+ }
+ };
+
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const computePassEncoder = encoder.beginComputePass();
+
+ const offset0 = 0;
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ UseBufferOnComputePassEncoder(computePassEncoder, buffer, usage0, offset0);
+
+ if (inSamePass) {
+ UseBufferOnComputePassEncoder(computePassEncoder, buffer, usage1, offset1);
+ computePassEncoder.end();
+ } else {
+ computePassEncoder.end();
+ const anotherComputePassEncoder = encoder.beginComputePass();
+ UseBufferOnComputePassEncoder(anotherComputePassEncoder, buffer, usage1, offset1);
+ anotherComputePassEncoder.end();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
+
+g.test('subresources,buffer_usage_in_one_render_pass_with_no_draw')
+ .desc(
+ `
+Test that when one buffer is used in one render pass encoder, its list of internal usages within one
+usage scope (all the commands in the whole render pass) can only be a compatible usage list even if
+there is no draw call in the render pass.
+ `
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage', 'vertex', 'index'])
+ .combine('usage1', ['uniform', 'storage', 'read-only-storage', 'vertex', 'index'])
+ .beginSubcases()
+ .combine('hasOverlap', [true, false])
+ .combine('visibility0', ['compute', 'fragment'])
+ .unless(t => t.visibility0 === 'compute' && !IsBufferUsageInBindGroup(t.usage0))
+ .combine('visibility1', ['compute', 'fragment'])
+ .unless(t => t.visibility1 === 'compute' && !IsBufferUsageInBindGroup(t.usage1))
+ )
+ .fn(async t => {
+ const { usage0, usage1, hasOverlap, visibility0, visibility1 } = t.params;
+
+ const UseBufferOnRenderPassEncoder = (
+ buffer,
+ offset,
+ type,
+ bindGroupVisibility,
+ renderPassEncoder
+ ) => {
+ switch (type) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup = t.createBindGroupForTest(buffer, offset, type, bindGroupVisibility);
+ renderPassEncoder.setBindGroup(0, bindGroup);
+ break;
+ }
+ case 'vertex': {
+ renderPassEncoder.setVertexBuffer(0, buffer, offset, kBoundBufferSize);
+ break;
+ }
+ case 'index': {
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16', offset, kBoundBufferSize);
+ break;
+ }
+ case 'indirect':
+ case 'indexedIndirect':
+ unreachable();
+ break;
+ }
+ };
+
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage:
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ const offset0 = 0;
+ UseBufferOnRenderPassEncoder(buffer, offset0, usage0, visibility0, renderPassEncoder);
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ UseBufferOnRenderPassEncoder(buffer, offset1, usage1, visibility1, renderPassEncoder);
+ renderPassEncoder.end();
+
+ const fail = (usage0 === 'storage') !== (usage1 === 'storage');
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, fail);
+ });
+
+g.test('subresources,buffer_usage_in_one_render_pass_with_one_draw')
+ .desc(
+ `
+Test that when one buffer is used in one render pass encoder where there is one draw call, its list
+of internal usages within one usage scope (all the commands in the whole render pass) can only be a
+compatible usage list. The usage scope rules are not related to the buffer offset or the bind group
+layout visibilities.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', kAllBufferUsages)
+ .combine('usage1', kAllBufferUsages)
+ .beginSubcases()
+ .combine('usage0AccessibleInDraw', [true, false])
+ .combine('usage1AccessibleInDraw', [true, false])
+ .combine('drawBeforeUsage1', [true, false])
+ .combine('visibility0', ['compute', 'fragment'])
+ .filter(t => {
+ // The buffer with `indirect` or `indexedIndirect` usage is always accessible in the draw
+ // call.
+ if (
+ (t.usage0 === 'indirect' || t.usage0 === 'indexedIndirect') &&
+ (!t.usage0AccessibleInDraw || t.visibility0 !== 'fragment' || !t.drawBeforeUsage1)
+ ) {
+ return false;
+ }
+ // The buffer usages `vertex` and `index` do nothing with shader visibilities.
+ if ((t.usage0 === 'vertex' || t.usage0 === 'index') && t.visibility0 !== 'fragment') {
+ return false;
+ }
+
+ // As usage0 is accessible in the draw call, visibility0 can only be 'fragment'.
+ if (t.usage0AccessibleInDraw && t.visibility0 !== 'fragment') {
+ return false;
+ }
+ // As usage1 is accessible in the draw call, the draw call cannot be before usage1.
+ if (t.drawBeforeUsage1 && t.usage1AccessibleInDraw) {
+ return false;
+ }
+ return true;
+ })
+ .combine('visibility1', ['compute', 'fragment'])
+ .filter(t => {
+ if (
+ (t.usage1 === 'indirect' || t.usage1 === 'indexedIndirect') &&
+ (!t.usage1AccessibleInDraw || t.visibility1 !== 'fragment' || t.drawBeforeUsage1)
+ ) {
+ return false;
+ }
+ if ((t.usage1 === 'vertex' || t.usage1 === 'index') && t.visibility1 !== 'fragment') {
+ return false;
+ }
+ // When the first buffer usage is `indirect` or `indexedIndirect`, there has already been
+ // one draw call, so in this test we always make the second usage inaccessible in the draw
+ // call.
+ if (
+ t.usage1AccessibleInDraw &&
+ (t.visibility1 !== 'fragment' ||
+ t.usage0 === 'indirect' ||
+ t.usage0 === 'indexedIndirect')
+ ) {
+ return false;
+ }
+ // When the first buffer usage is `index` and is accessible in the draw call, the second
+ // usage cannot be `indirect` (it should be `indexedIndirect` for the tests on indirect draw
+ // calls)
+ if (t.usage0 === 'index' && t.usage0AccessibleInDraw && t.usage1 === 'indirect') {
+ return false;
+ }
+ return true;
+ })
+ .combine('hasOverlap', [true, false])
+ )
+ .fn(async t => {
+ const {
+ // Buffer with usage0 will be "used" in the draw call if this value is true.
+ usage0AccessibleInDraw,
+ // Buffer with usage1 will be "used" in the draw call if this value is true.
+ usage1AccessibleInDraw,
+ // Whether we will have the draw call before setting the buffer usage as "usage1" or not.
+ // If it is true: set-usage0 -> draw -> set-usage1 or indirect-draw -> set-usage1
+ // Otherwise: set-usage0 -> set-usage1 -> draw or set-usage0 -> indirect-draw
+ drawBeforeUsage1,
+ usage0,
+ visibility0,
+ usage1,
+ visibility1,
+ hasOverlap,
+ } = t.params;
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage:
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX |
+ GPUBufferUsage.INDIRECT,
+ });
+
+ const UseBufferOnRenderPassEncoder = (
+ bufferAccessibleInDraw,
+ bufferIndex,
+ offset,
+ usage,
+ bindGroupVisibility,
+ renderPassEncoder,
+ usedBindGroupLayouts
+ ) => {
+ switch (usage) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup = t.createBindGroupForTest(buffer, offset, usage, bindGroupVisibility);
+ renderPassEncoder.setBindGroup(bufferIndex, bindGroup);
+ // To "use" the bind group we will set the corresponding bind group layout in the
+ // pipeline layout when creating the render pipeline.
+ if (bufferAccessibleInDraw && bindGroupVisibility === 'fragment') {
+ usedBindGroupLayouts.push(t.createBindGroupLayoutForTest(usage, bindGroupVisibility));
+ }
+ break;
+ }
+ case 'vertex': {
+ renderPassEncoder.setVertexBuffer(bufferIndex, buffer, offset);
+ break;
+ }
+ case 'index': {
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16', offset);
+ break;
+ }
+ case 'indirect':
+ case 'indexedIndirect': {
+ // We will handle the indirect draw calls later.
+ break;
+ }
+ }
+ };
+
+ const MakeDrawCallWithOneUsage = (usage, offset, renderPassEncoder) => {
+ switch (usage) {
+ case 'uniform':
+ case 'read-only-storage':
+ case 'storage':
+ case 'vertex':
+ renderPassEncoder.draw(1);
+ break;
+ case 'index':
+ renderPassEncoder.drawIndexed(1);
+ break;
+ case 'indirect':
+ renderPassEncoder.drawIndirect(buffer, offset);
+ break;
+ case 'indexedIndirect': {
+ const indexBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ renderPassEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ renderPassEncoder.drawIndexedIndirect(buffer, offset);
+ break;
+ }
+ }
+ };
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+
+ // Set buffer with usage0
+ const offset0 = 0;
+ // Invisible bind groups or vertex buffers are all bound to the slot 1.
+ const bufferIndex0 = visibility0 === 'fragment' ? 0 : 1;
+ const usedBindGroupLayouts = [];
+
+ UseBufferOnRenderPassEncoder(
+ usage0AccessibleInDraw,
+ bufferIndex0,
+ offset0,
+ usage0,
+ visibility0,
+ renderPassEncoder,
+ usedBindGroupLayouts
+ );
+
+ let vertexBufferCount = 0;
+
+ // Set pipeline and do draw call if drawBeforeUsage1 === true
+ if (drawBeforeUsage1) {
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: usedBindGroupLayouts,
+ });
+ // To "use" the vertex buffer we need to set the corresponding vertex buffer layout when
+ // creating the render pipeline.
+ if (usage0 === 'vertex' && usage0AccessibleInDraw) {
+ ++vertexBufferCount;
+ }
+ const pipeline = t.createRenderPipelineForTest(pipelineLayout, vertexBufferCount);
+ renderPassEncoder.setPipeline(pipeline);
+ if (!usage0AccessibleInDraw) {
+ renderPassEncoder.draw(1);
+ } else {
+ MakeDrawCallWithOneUsage(usage0, offset0, renderPassEncoder);
+ }
+ }
+
+ // Set buffer with usage1.
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ let bufferIndex1 = 0;
+ if (visibility1 !== 'fragment') {
+ // Invisible bind groups or vertex buffers are all bound to the slot 1.
+ bufferIndex1 = 1;
+ } else if (visibility0 === 'fragment' && usage0AccessibleInDraw) {
+ // When buffer is bound to different bind groups or bound as vertex buffers in one render pass
+ // encoder, the second buffer binding should consume the slot 1.
+ if (IsBufferUsageInBindGroup(usage0) && IsBufferUsageInBindGroup(usage1)) {
+ bufferIndex1 = 1;
+ } else if (usage0 === 'vertex' && usage1 === 'vertex') {
+ bufferIndex1 = 1;
+ }
+ }
+
+ UseBufferOnRenderPassEncoder(
+ usage1AccessibleInDraw,
+ bufferIndex1,
+ offset1,
+ usage1,
+ visibility1,
+ renderPassEncoder,
+ usedBindGroupLayouts
+ );
+
+ // Set pipeline and do draw call if drawBeforeUsage1 === false
+ if (!drawBeforeUsage1) {
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: usedBindGroupLayouts,
+ });
+ if (usage1 === 'vertex' && usage1AccessibleInDraw) {
+ // To "use" the vertex buffer we need to set the corresponding vertex buffer layout when
+ // creating the render pipeline.
+ ++vertexBufferCount;
+ }
+ const pipeline = t.createRenderPipelineForTest(pipelineLayout, vertexBufferCount);
+ renderPassEncoder.setPipeline(pipeline);
+
+ assert(usage0 !== 'indirect');
+ if (!usage0AccessibleInDraw && !usage1AccessibleInDraw) {
+ renderPassEncoder.draw(1);
+ } else if (usage0AccessibleInDraw && !usage1AccessibleInDraw) {
+ MakeDrawCallWithOneUsage(usage0, offset0, renderPassEncoder);
+ } else if (!usage0AccessibleInDraw && usage1AccessibleInDraw) {
+ MakeDrawCallWithOneUsage(usage1, offset1, renderPassEncoder);
+ } else {
+ if (usage1 === 'indexedIndirect') {
+ // If the index buffer has already been set (as usage0), we won't need to set another
+ // index buffer.
+ if (usage0 !== 'index') {
+ const indexBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ renderPassEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ }
+ renderPassEncoder.drawIndexedIndirect(buffer, offset1);
+ } else if (usage1 === 'indirect') {
+ assert(usage0 !== 'index');
+ renderPassEncoder.drawIndirect(buffer, offset1);
+ } else if (usage0 === 'index' || usage1 === 'index') {
+ // We need to call drawIndexed to "use" the index buffer (as usage0 or usage1).
+ renderPassEncoder.drawIndexed(1);
+ } else {
+ renderPassEncoder.draw(1);
+ }
+ }
+ }
+ renderPassEncoder.end();
+
+ const fail = (usage0 === 'storage') !== (usage1 === 'storage');
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, fail);
+ });
+
+g.test('subresources,buffer_usage_in_one_render_pass_with_two_draws')
+ .desc(
+ `
+Test that when one buffer is used in different draw calls in one render pass, its list of internal
+usages within one usage scope (all the commands in the whole render pass) can only be a compatible
+usage list, and the usage scope rules are not related to the buffer offset, while the draw calls in
+different render pass encoders belong to different usage scopes.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', kAllBufferUsages)
+ .combine('usage1', kAllBufferUsages)
+ .beginSubcases()
+ .combine('inSamePass', [true, false])
+ .combine('hasOverlap', [true, false])
+ )
+ .fn(async t => {
+ const { usage0, usage1, inSamePass, hasOverlap } = t.params;
+ const buffer = t.createBufferWithState('valid', {
+ size: kBoundBufferSize * 2,
+ usage:
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX |
+ GPUBufferUsage.INDIRECT,
+ });
+ const UseBufferOnRenderPassEncoderInDrawCall = (offset, usage, renderPassEncoder) => {
+ switch (usage) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroupLayout = t.createBindGroupLayoutForTest(usage, 'fragment');
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ });
+ const pipeline = t.createRenderPipelineForTest(pipelineLayout, 0);
+ renderPassEncoder.setPipeline(pipeline);
+ const bindGroup = t.createBindGroupForTest(buffer, offset, usage, 'fragment');
+ renderPassEncoder.setBindGroup(0, bindGroup);
+ renderPassEncoder.draw(1);
+ break;
+ }
+ case 'vertex': {
+ const kVertexBufferCount = 1;
+ const pipeline = t.createRenderPipelineForTest('auto', kVertexBufferCount);
+ renderPassEncoder.setPipeline(pipeline);
+ renderPassEncoder.setVertexBuffer(0, buffer, offset);
+ renderPassEncoder.draw(1);
+ break;
+ }
+ case 'index': {
+ const pipeline = t.createRenderPipelineForTest('auto', 0);
+ renderPassEncoder.setPipeline(pipeline);
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16', offset);
+ renderPassEncoder.drawIndexed(1);
+ break;
+ }
+ case 'indirect': {
+ const pipeline = t.createRenderPipelineForTest('auto', 0);
+ renderPassEncoder.setPipeline(pipeline);
+ renderPassEncoder.drawIndirect(buffer, offset);
+ break;
+ }
+ case 'indexedIndirect': {
+ const pipeline = t.createRenderPipelineForTest('auto', 0);
+ renderPassEncoder.setPipeline(pipeline);
+ const indexBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ renderPassEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ renderPassEncoder.drawIndexedIndirect(buffer, offset);
+ break;
+ }
+ }
+ };
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+
+ const offset0 = 0;
+ UseBufferOnRenderPassEncoderInDrawCall(offset0, usage0, renderPassEncoder);
+
+ const offset1 = hasOverlap ? offset0 : kBoundBufferSize;
+ if (inSamePass) {
+ UseBufferOnRenderPassEncoderInDrawCall(offset1, usage1, renderPassEncoder);
+ renderPassEncoder.end();
+ } else {
+ renderPassEncoder.end();
+ const anotherRenderPassEncoder = t.beginSimpleRenderPass(encoder);
+ UseBufferOnRenderPassEncoderInDrawCall(offset1, usage1, anotherRenderPassEncoder);
+ anotherRenderPassEncoder.end();
+ }
+
+ const fail = inSamePass && (usage0 === 'storage') !== (usage1 === 'storage');
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, fail);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_misc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_misc.spec.js
new file mode 100644
index 0000000000..b48dcf954d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/buffer/in_pass_misc.spec.js
@@ -0,0 +1,404 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test other buffer usage validation rules that are not tests in ./in_pass_encoder.spec.js.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../../common/util/util.js';
+
+import { BufferResourceUsageTest, kAllBufferUsages } from './in_pass_encoder.spec.js';
+
+export const g = makeTestGroup(BufferResourceUsageTest);
+
+const kBufferSize = 256;
+
+g.test('subresources,reset_buffer_usage_before_dispatch')
+ .desc(
+ `
+Test that the buffer usages which are reset by another state-setting commands before a dispatch call
+do not contribute directly to any usage scope in a compute pass.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage'])
+ .combine('usage1', ['uniform', 'storage', 'read-only-storage', 'indirect'])
+ )
+ .fn(async t => {
+ const { usage0, usage1 } = t.params;
+
+ const kUsages = GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT;
+ const buffer = t.createBufferWithState('valid', {
+ size: kBufferSize,
+ usage: kUsages,
+ });
+ const anotherBuffer = t.createBufferWithState('valid', {
+ size: kBufferSize,
+ usage: kUsages,
+ });
+
+ const bindGroupLayouts = [t.createBindGroupLayoutForTest(usage0, 'compute')];
+
+ if (usage1 !== 'indirect') {
+ bindGroupLayouts.push(t.createBindGroupLayoutForTest(usage1, 'compute'));
+ }
+ const pipelineLayout = t.device.createPipelineLayout({ bindGroupLayouts });
+ const computePipeline = t.createNoOpComputePipeline(pipelineLayout);
+
+ const encoder = t.device.createCommandEncoder();
+ const computePassEncoder = encoder.beginComputePass();
+ computePassEncoder.setPipeline(computePipeline);
+
+ // Set usage0 for buffer at bind group index 0
+ const bindGroup0 = t.createBindGroupForTest(buffer, 0, usage0, 'compute');
+ computePassEncoder.setBindGroup(0, bindGroup0);
+
+ // Reset bind group index 0 with another bind group that uses anotherBuffer
+ const anotherBindGroup = t.createBindGroupForTest(anotherBuffer, 0, usage0, 'compute');
+ computePassEncoder.setBindGroup(0, anotherBindGroup);
+
+ // Set usage1 for buffer
+ switch (usage1) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup1 = t.createBindGroupForTest(buffer, 0, usage1, 'compute');
+ computePassEncoder.setBindGroup(1, bindGroup1);
+ computePassEncoder.dispatchWorkgroups(1);
+ break;
+ }
+ case 'indirect': {
+ computePassEncoder.dispatchWorkgroupsIndirect(buffer, 0);
+ break;
+ }
+ }
+
+ computePassEncoder.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
+
+g.test('subresources,reset_buffer_usage_before_draw')
+ .desc(
+ `
+Test that the buffer usages which are reset by another state-setting commands before a draw call
+still contribute directly to the usage scope of the draw call.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['uniform', 'storage', 'read-only-storage', 'vertex', 'index'])
+ .combine('usage1', kAllBufferUsages)
+ .unless(t => {
+ return t.usage0 === 'index' && t.usage1 === 'indirect';
+ })
+ )
+ .fn(async t => {
+ const { usage0, usage1 } = t.params;
+
+ const kUsages =
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.INDIRECT |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX;
+ const buffer = t.createBufferWithState('valid', {
+ size: kBufferSize,
+ usage: kUsages,
+ });
+ const anotherBuffer = t.createBufferWithState('valid', {
+ size: kBufferSize,
+ usage: kUsages,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+
+ const bindGroupLayouts = [];
+ let vertexBufferCount = 0;
+
+ // Set buffer as usage0 and reset buffer with anotherBuffer as usage0
+ switch (usage0) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup0 = t.createBindGroupForTest(buffer, 0, usage0, 'fragment');
+ renderPassEncoder.setBindGroup(bindGroupLayouts.length, bindGroup0);
+
+ const anotherBindGroup = t.createBindGroupForTest(anotherBuffer, 0, usage0, 'fragment');
+ renderPassEncoder.setBindGroup(bindGroupLayouts.length, anotherBindGroup);
+
+ bindGroupLayouts.push(t.createBindGroupLayoutForTest(usage0, 'fragment'));
+ break;
+ }
+ case 'vertex': {
+ renderPassEncoder.setVertexBuffer(vertexBufferCount, buffer);
+ renderPassEncoder.setVertexBuffer(vertexBufferCount, anotherBuffer);
+
+ ++vertexBufferCount;
+ break;
+ }
+ case 'index': {
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16');
+ renderPassEncoder.setIndexBuffer(anotherBuffer, 'uint16');
+ break;
+ }
+ }
+
+ // Set buffer as usage1
+ switch (usage1) {
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup1 = t.createBindGroupForTest(buffer, 0, usage1, 'fragment');
+ renderPassEncoder.setBindGroup(bindGroupLayouts.length, bindGroup1);
+
+ bindGroupLayouts.push(t.createBindGroupLayoutForTest(usage1, 'fragment'));
+ break;
+ }
+ case 'vertex': {
+ renderPassEncoder.setVertexBuffer(vertexBufferCount, buffer);
+ ++vertexBufferCount;
+ break;
+ }
+ case 'index': {
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16');
+ break;
+ }
+ case 'indirect':
+ case 'indexedIndirect':
+ break;
+ }
+
+ // Add draw call
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts,
+ });
+ const renderPipeline = t.createRenderPipelineForTest(pipelineLayout, vertexBufferCount);
+ renderPassEncoder.setPipeline(renderPipeline);
+ switch (usage1) {
+ case 'indexedIndirect': {
+ if (usage0 !== 'index') {
+ const indexBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ renderPassEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ }
+ renderPassEncoder.drawIndexedIndirect(buffer, 0);
+ break;
+ }
+ case 'indirect': {
+ renderPassEncoder.drawIndirect(buffer, 0);
+ break;
+ }
+ case 'index': {
+ renderPassEncoder.drawIndexed(1);
+ break;
+ }
+ case 'vertex':
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ if (usage0 === 'index') {
+ renderPassEncoder.drawIndexed(1);
+ } else {
+ renderPassEncoder.draw(1);
+ }
+ break;
+ }
+ }
+
+ renderPassEncoder.end();
+
+ const fail = (usage0 === 'storage') !== (usage1 === 'storage');
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, fail);
+ });
+
+g.test('subresources,buffer_usages_in_copy_and_pass')
+ .desc(
+ `
+ Test that using one buffer in a copy command, a render or compute pass encoder is always allowed
+ as WebGPU SPEC (chapter 3.4.5) defines that out of any pass encoder, each command belongs to one
+ separated usage scope.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', [
+ 'copy-src',
+ 'copy-dst',
+ 'uniform',
+ 'storage',
+ 'read-only-storage',
+ 'vertex',
+ 'index',
+ 'indirect',
+ 'indexedIndirect',
+ ])
+ .combine('usage1', [
+ 'copy-src',
+ 'copy-dst',
+ 'uniform',
+ 'storage',
+ 'read-only-storage',
+ 'vertex',
+ 'index',
+ 'indirect',
+ 'indexedIndirect',
+ ])
+ .combine('pass', ['render', 'compute'])
+ .unless(({ usage0, usage1, pass }) => {
+ const IsCopy = usage => {
+ return usage === 'copy-src' || usage === 'copy-dst';
+ };
+ // We intend to test copy usages in this test.
+ if (!IsCopy(usage0) && !IsCopy(usage1)) {
+ return true;
+ }
+ // When both usage0 and usage1 are copy usages, 'pass' is meaningless so in such situation
+ // we just need to reserve one value as 'pass'.
+ if (IsCopy(usage0) && IsCopy(usage1)) {
+ return pass === 'compute';
+ }
+
+ const IsValidComputeUsage = usage => {
+ switch (usage) {
+ case 'vertex':
+ case 'index':
+ case 'indexedIndirect':
+ return false;
+ default:
+ return true;
+ }
+ };
+ if (pass === 'compute') {
+ return !IsValidComputeUsage(usage0) || !IsValidComputeUsage(usage1);
+ }
+
+ return false;
+ })
+ )
+ .fn(async t => {
+ const { usage0, usage1, pass } = t.params;
+
+ const kUsages =
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.COPY_DST |
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.INDIRECT |
+ GPUBufferUsage.VERTEX |
+ GPUBufferUsage.INDEX;
+ const buffer = t.createBufferWithState('valid', {
+ size: kBufferSize,
+ usage: kUsages,
+ });
+
+ const UseBufferOnCommandEncoder = (
+ usage,
+
+ encoder
+ ) => {
+ switch (usage) {
+ case 'copy-src': {
+ const destinationBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ encoder.copyBufferToBuffer(buffer, 0, destinationBuffer, 0, 4);
+ break;
+ }
+ case 'copy-dst': {
+ const sourceBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ encoder.copyBufferToBuffer(sourceBuffer, 0, buffer, 0, 4);
+ break;
+ }
+ case 'uniform':
+ case 'storage':
+ case 'read-only-storage': {
+ const bindGroup = t.createBindGroupForTest(buffer, 0, usage, 'fragment');
+ switch (pass) {
+ case 'render': {
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ renderPassEncoder.setBindGroup(0, bindGroup);
+ renderPassEncoder.end();
+ break;
+ }
+ case 'compute': {
+ const computePassEncoder = encoder.beginComputePass();
+ computePassEncoder.setBindGroup(0, bindGroup);
+ computePassEncoder.end();
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ break;
+ }
+ case 'vertex': {
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ renderPassEncoder.setVertexBuffer(0, buffer);
+ renderPassEncoder.end();
+ break;
+ }
+ case 'index': {
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ renderPassEncoder.setIndexBuffer(buffer, 'uint16');
+ renderPassEncoder.end();
+ break;
+ }
+ case 'indirect': {
+ switch (pass) {
+ case 'render': {
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ const renderPipeline = t.createNoOpRenderPipeline();
+ renderPassEncoder.setPipeline(renderPipeline);
+ renderPassEncoder.drawIndirect(buffer, 0);
+ renderPassEncoder.end();
+ break;
+ }
+ case 'compute': {
+ const computePassEncoder = encoder.beginComputePass();
+ const computePipeline = t.createNoOpComputePipeline();
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroupsIndirect(buffer, 0);
+ computePassEncoder.end();
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ break;
+ }
+ case 'indexedIndirect': {
+ const renderPassEncoder = t.beginSimpleRenderPass(encoder);
+ const renderPipeline = t.createNoOpRenderPipeline();
+ renderPassEncoder.setPipeline(renderPipeline);
+ const indexBuffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.INDEX,
+ });
+ renderPassEncoder.setIndexBuffer(indexBuffer, 'uint16');
+ renderPassEncoder.drawIndexedIndirect(buffer, 0);
+ renderPassEncoder.end();
+ break;
+ }
+ default:
+ unreachable();
+ }
+ };
+
+ const encoder = t.device.createCommandEncoder();
+ UseBufferOnCommandEncoder(usage0, encoder);
+ UseBufferOnCommandEncoder(usage1, encoder);
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js
new file mode 100644
index 0000000000..18cfe55a42
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.js
@@ -0,0 +1,1338 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Texture Usages Validation Tests in Render Pass and Compute Pass.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { pp } from '../../../../../common/util/preprocessor.js';
+import { assert } from '../../../../../common/util/util.js';
+import {
+ kDepthStencilFormats,
+ kDepthStencilFormatResolvedAspect,
+ kTextureFormatInfo,
+} from '../../../../capability_info.js';
+import { GPUConst } from '../../../../constants.js';
+import { ValidationTest } from '../../validation_test.js';
+
+const kTextureBindingTypes = [
+ 'sampled-texture',
+ 'multisampled-texture',
+ 'writeonly-storage-texture',
+];
+
+const SIZE = 32;
+class TextureUsageTracking extends ValidationTest {
+ createTexture(options = {}) {
+ const {
+ width = SIZE,
+ height = SIZE,
+ arrayLayerCount = 1,
+ mipLevelCount = 1,
+ sampleCount = 1,
+ format = 'rgba8unorm',
+ usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ } = options;
+
+ return this.device.createTexture({
+ size: { width, height, depthOrArrayLayers: arrayLayerCount },
+ mipLevelCount,
+ sampleCount,
+ dimension: '2d',
+ format,
+ usage,
+ });
+ }
+
+ createBindGroupLayout(binding, bindingType, viewDimension, options = {}) {
+ const { sampleType, format } = options;
+ let entry;
+ switch (bindingType) {
+ case 'sampled-texture':
+ entry = { texture: { viewDimension, sampleType } };
+ break;
+ case 'multisampled-texture':
+ entry = { texture: { viewDimension, multisampled: true, sampleType } };
+ break;
+ case 'writeonly-storage-texture':
+ assert(format !== undefined);
+ entry = { storageTexture: { access: 'write-only', format, viewDimension } };
+ break;
+ }
+
+ return this.device.createBindGroupLayout({
+ entries: [
+ { binding, visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT, ...entry },
+ ],
+ });
+ }
+
+ createBindGroup(binding, resource, bindingType, viewDimension, options = {}) {
+ return this.device.createBindGroup({
+ entries: [{ binding, resource }],
+ layout: this.createBindGroupLayout(binding, bindingType, viewDimension, options),
+ });
+ }
+
+ createAndExecuteBundle(binding, bindGroup, pass, depthStencilFormat) {
+ const bundleEncoder = this.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ depthStencilFormat,
+ });
+ bundleEncoder.setBindGroup(binding, bindGroup);
+ const bundle = bundleEncoder.finish();
+ pass.executeBundles([bundle]);
+ }
+
+ beginSimpleRenderPass(encoder, view) {
+ return encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view,
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ }
+
+ /**
+ * Create two bind groups. Resource usages conflict between these two bind groups. But resource
+ * usage inside each bind group doesn't conflict.
+ */
+ makeConflictingBindGroups() {
+ const view = this.createTexture({
+ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
+ }).createView();
+ const bindGroupLayouts = [
+ this.createBindGroupLayout(0, 'sampled-texture', '2d'),
+ this.createBindGroupLayout(0, 'writeonly-storage-texture', '2d', { format: 'rgba8unorm' }),
+ ];
+
+ return {
+ bindGroupLayouts,
+ bindGroups: [
+ this.device.createBindGroup({
+ layout: bindGroupLayouts[0],
+ entries: [{ binding: 0, resource: view }],
+ }),
+ this.device.createBindGroup({
+ layout: bindGroupLayouts[1],
+ entries: [{ binding: 0, resource: view }],
+ }),
+ ],
+ };
+ }
+
+ testValidationScope(compute) {
+ const { bindGroupLayouts, bindGroups } = this.makeConflictingBindGroups();
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = compute
+ ? encoder.beginComputePass()
+ : this.beginSimpleRenderPass(encoder, this.createTexture().createView());
+
+ // Create pipeline. Note that bindings unused in pipeline should be validated too.
+ const pipelineLayout = this.device.createPipelineLayout({
+ bindGroupLayouts,
+ });
+ const pipeline = compute
+ ? this.createNoOpComputePipeline(pipelineLayout)
+ : this.createNoOpRenderPipeline(pipelineLayout);
+ return {
+ bindGroup0: bindGroups[0],
+ bindGroup1: bindGroups[1],
+ encoder,
+ pass,
+ pipeline,
+ };
+ }
+
+ setPipeline(pass, pipeline) {
+ if (pass instanceof GPUComputePassEncoder) {
+ pass.setPipeline(pipeline);
+ } else {
+ pass.setPipeline(pipeline);
+ }
+ }
+
+ issueDrawOrDispatch(pass) {
+ if (pass instanceof GPUComputePassEncoder) {
+ pass.dispatchWorkgroups(1);
+ } else {
+ pass.draw(3, 1, 0, 0);
+ }
+ }
+
+ setComputePipelineAndCallDispatch(pass, layout) {
+ const pipeline = this.createNoOpComputePipeline(layout);
+ pass.setPipeline(pipeline);
+ pass.dispatchWorkgroups(1);
+ }
+}
+
+export const g = makeTestGroup(TextureUsageTracking);
+
+const BASE_LEVEL = 1;
+const TOTAL_LEVELS = 6;
+const BASE_LAYER = 1;
+const TOTAL_LAYERS = 6;
+const SLICE_COUNT = 2;
+
+g.test('subresources_and_binding_types_combination_for_color')
+ .desc(
+ `
+ Test the resource usage rules by using two views of the same GPUTexture in a usage scope. Tests
+ various combinations of {sampled, storage, render target} usages, mip-level ranges, and
+ array-layer ranges, in {compute pass, render pass, render pass via bundle}.
+ - Error if a subresource (level/layer) is used as read+write or write+write in the scope,
+ except when both usages are writeonly-storage-texture which is allowed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('compute', [false, true])
+ .combineWithParams([
+ { _usageOK: true, type0: 'sampled-texture', type1: 'sampled-texture' },
+ { _usageOK: false, type0: 'sampled-texture', type1: 'writeonly-storage-texture' },
+ { _usageOK: false, type0: 'sampled-texture', type1: 'render-target' },
+ // Race condition upon multiple writable storage texture is valid.
+ { _usageOK: true, type0: 'writeonly-storage-texture', type1: 'writeonly-storage-texture' },
+ { _usageOK: false, type0: 'writeonly-storage-texture', type1: 'render-target' },
+ { _usageOK: false, type0: 'render-target', type1: 'render-target' },
+ ])
+ .beginSubcases()
+ .combine('binding0InBundle', [false, true])
+ .combine('binding1InBundle', [false, true])
+ .unless(
+ p =>
+ // We can't set 'render-target' in bundle, so we need to exclude it from bundle.
+ (p.binding0InBundle && p.type0 === 'render-target') ||
+ (p.binding1InBundle && p.type1 === 'render-target') ||
+ // We can't set 'render-target' or bundle in compute.
+ (p.compute &&
+ (p.binding0InBundle ||
+ p.binding1InBundle ||
+ p.type0 === 'render-target' ||
+ p.type1 === 'render-target'))
+ )
+ .combineWithParams([
+ // Two texture usages are binding to the same texture subresource.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL,
+ levelCount1: 1,
+ baseLayer1: BASE_LAYER,
+ layerCount1: 1,
+ _resourceSuccess: false,
+ },
+
+ // Two texture usages are binding to different mip levels of the same texture.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL + 1,
+ levelCount1: 1,
+ baseLayer1: BASE_LAYER,
+ layerCount1: 1,
+ _resourceSuccess: true,
+ },
+
+ // Two texture usages are binding to different array layers of the same texture.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL,
+ levelCount1: 1,
+ baseLayer1: BASE_LAYER + 1,
+ layerCount1: 1,
+ _resourceSuccess: true,
+ },
+
+ // The second texture usage contains the whole mip chain where the first texture usage is
+ // using.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: 0,
+ levelCount1: TOTAL_LEVELS,
+ baseLayer1: BASE_LAYER,
+ layerCount1: 1,
+ _resourceSuccess: false,
+ },
+
+ // The second texture usage contains all layers where the first texture usage is using.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL,
+ levelCount1: 1,
+ baseLayer1: 0,
+ layerCount1: TOTAL_LAYERS,
+ _resourceSuccess: false,
+ },
+
+ // The second texture usage contains all subresources where the first texture usage is
+ // using.
+ {
+ levelCount0: 1,
+ layerCount0: 1,
+ baseLevel1: 0,
+ levelCount1: TOTAL_LEVELS,
+ baseLayer1: 0,
+ layerCount1: TOTAL_LAYERS,
+ _resourceSuccess: false,
+ },
+
+ // Both of the two usages access a few mip levels on the same layer but they don't overlap.
+ {
+ levelCount0: SLICE_COUNT,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL + SLICE_COUNT,
+ levelCount1: 3,
+ baseLayer1: BASE_LAYER,
+ layerCount1: 1,
+ _resourceSuccess: true,
+ },
+
+ // Both of the two usages access a few mip levels on the same layer and they overlap.
+ {
+ levelCount0: SLICE_COUNT,
+ layerCount0: 1,
+ baseLevel1: BASE_LEVEL + SLICE_COUNT - 1,
+ levelCount1: 3,
+ baseLayer1: BASE_LAYER,
+ layerCount1: 1,
+ _resourceSuccess: false,
+ },
+
+ // Both of the two usages access a few array layers on the same level but they don't
+ // overlap.
+ {
+ levelCount0: 1,
+ layerCount0: SLICE_COUNT,
+ baseLevel1: BASE_LEVEL,
+ levelCount1: 1,
+ baseLayer1: BASE_LAYER + SLICE_COUNT,
+ layerCount1: 3,
+ _resourceSuccess: true,
+ },
+
+ // Both of the two usages access a few array layers on the same level and they overlap.
+ {
+ levelCount0: 1,
+ layerCount0: SLICE_COUNT,
+ baseLevel1: BASE_LEVEL,
+ levelCount1: 1,
+ baseLayer1: BASE_LAYER + SLICE_COUNT - 1,
+ layerCount1: 3,
+ _resourceSuccess: false,
+ },
+
+ // Both of the two usages access a few array layers and mip levels but they don't overlap.
+ {
+ levelCount0: SLICE_COUNT,
+ layerCount0: SLICE_COUNT,
+ baseLevel1: BASE_LEVEL + SLICE_COUNT,
+ levelCount1: 3,
+ baseLayer1: BASE_LAYER + SLICE_COUNT,
+ layerCount1: 3,
+ _resourceSuccess: true,
+ },
+
+ // Both of the two usages access a few array layers and mip levels and they overlap.
+ {
+ levelCount0: SLICE_COUNT,
+ layerCount0: SLICE_COUNT,
+ baseLevel1: BASE_LEVEL + SLICE_COUNT - 1,
+ levelCount1: 3,
+ baseLayer1: BASE_LAYER + SLICE_COUNT - 1,
+ layerCount1: 3,
+ _resourceSuccess: false,
+ },
+ ])
+ .unless(
+ p =>
+ // Every color attachment or storage texture can use only one single subresource.
+ (p.type0 !== 'sampled-texture' && (p.levelCount0 !== 1 || p.layerCount0 !== 1)) ||
+ (p.type1 !== 'sampled-texture' && (p.levelCount1 !== 1 || p.layerCount1 !== 1)) ||
+ // All color attachments' size should be the same.
+ (p.type0 === 'render-target' &&
+ p.type1 === 'render-target' &&
+ p.baseLevel1 !== BASE_LEVEL)
+ )
+ )
+ .fn(t => {
+ const {
+ compute,
+ binding0InBundle,
+ binding1InBundle,
+ levelCount0,
+ layerCount0,
+ baseLevel1,
+ baseLayer1,
+ levelCount1,
+ layerCount1,
+ type0,
+ type1,
+ _usageOK,
+ _resourceSuccess,
+ } = t.params;
+
+ const texture = t.createTexture({
+ arrayLayerCount: TOTAL_LAYERS,
+ mipLevelCount: TOTAL_LEVELS,
+ usage:
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.STORAGE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const dimension0 = layerCount0 !== 1 ? '2d-array' : '2d';
+ const view0 = texture.createView({
+ dimension: dimension0,
+ baseMipLevel: BASE_LEVEL,
+ mipLevelCount: levelCount0,
+ baseArrayLayer: BASE_LAYER,
+ arrayLayerCount: layerCount0,
+ });
+
+ const dimension1 = layerCount1 !== 1 ? '2d-array' : '2d';
+ const view1 = texture.createView({
+ dimension: dimension1,
+ baseMipLevel: baseLevel1,
+ mipLevelCount: levelCount1,
+ baseArrayLayer: baseLayer1,
+ arrayLayerCount: layerCount1,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ if (type0 === 'render-target') {
+ // Note that type1 is 'render-target' too. So we don't need to create bindings.
+ assert(type1 === 'render-target');
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: view0,
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ {
+ view: view1,
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ } else {
+ const pass = compute
+ ? encoder.beginComputePass()
+ : t.beginSimpleRenderPass(
+ encoder,
+ type1 === 'render-target' ? view1 : t.createTexture().createView()
+ );
+
+ const bgls = [];
+ // Create bind groups. Set bind groups in pass directly or set bind groups in bundle.
+ const storageTextureFormat0 = type0 === 'sampled-texture' ? undefined : 'rgba8unorm';
+
+ const bgl0 = t.createBindGroupLayout(0, type0, dimension0, { format: storageTextureFormat0 });
+ const bindGroup0 = t.device.createBindGroup({
+ layout: bgl0,
+ entries: [{ binding: 0, resource: view0 }],
+ });
+ bgls.push(bgl0);
+
+ if (binding0InBundle) {
+ assert(pass instanceof GPURenderPassEncoder);
+ t.createAndExecuteBundle(0, bindGroup0, pass);
+ } else {
+ pass.setBindGroup(0, bindGroup0);
+ }
+ if (type1 !== 'render-target') {
+ const storageTextureFormat1 = type1 === 'sampled-texture' ? undefined : 'rgba8unorm';
+
+ const bgl1 = t.createBindGroupLayout(1, type1, dimension1, {
+ format: storageTextureFormat1,
+ });
+ const bindGroup1 = t.device.createBindGroup({
+ layout: bgl1,
+ entries: [{ binding: 1, resource: view1 }],
+ });
+ bgls.push(bgl1);
+
+ if (binding1InBundle) {
+ assert(pass instanceof GPURenderPassEncoder);
+ t.createAndExecuteBundle(1, bindGroup1, pass);
+ } else {
+ pass.setBindGroup(1, bindGroup1);
+ }
+ }
+ if (compute) {
+ t.setComputePipelineAndCallDispatch(
+ pass,
+ t.device.createPipelineLayout({ bindGroupLayouts: bgls })
+ );
+ }
+ pass.end();
+ }
+
+ const success = _resourceSuccess || _usageOK;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources_and_binding_types_combination_for_aspect')
+ .desc(
+ `
+ Test the resource usage rules by using two views of the same GPUTexture in a usage scope. Tests
+ various combinations of {sampled, render target} usages, {all, depth-only, stencil-only} aspects
+ that overlap a given subresources in {compute pass, render pass, render pass via bundle}.
+ - Error if a subresource (level/layer/aspect) is used as read+write or write+write in the
+ scope.
+ `
+ )
+ .params(u =>
+ u
+ .combine('compute', [false, true])
+ .combine('binding0InBundle', [false, true])
+ .combine('binding1InBundle', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .beginSubcases()
+ .combineWithParams([
+ {
+ baseLevel: BASE_LEVEL,
+ baseLayer: BASE_LAYER,
+ _resourceSuccess: false,
+ },
+ {
+ baseLevel: BASE_LEVEL + 1,
+ baseLayer: BASE_LAYER,
+ _resourceSuccess: true,
+ },
+ {
+ baseLevel: BASE_LEVEL,
+ baseLayer: BASE_LAYER + 1,
+ _resourceSuccess: true,
+ },
+ ])
+ .combine('aspect0', ['all', 'depth-only', 'stencil-only'])
+ .combine('aspect1', ['all', 'depth-only', 'stencil-only'])
+ .unless(
+ p =>
+ (p.aspect0 === 'stencil-only' && !kTextureFormatInfo[p.format].stencil) ||
+ (p.aspect1 === 'stencil-only' && !kTextureFormatInfo[p.format].stencil)
+ )
+ .unless(
+ p =>
+ (p.aspect0 === 'depth-only' && !kTextureFormatInfo[p.format].depth) ||
+ (p.aspect1 === 'depth-only' && !kTextureFormatInfo[p.format].depth)
+ )
+ .combineWithParams([
+ {
+ type0: 'sampled-texture',
+ type1: 'sampled-texture',
+ _usageSuccess: true,
+ },
+ {
+ type0: 'sampled-texture',
+ type1: 'render-target',
+ _usageSuccess: false,
+ },
+ ])
+ .unless(
+ // Can't sample a multiplanar texture without selecting an aspect.
+ p =>
+ kTextureFormatInfo[p.format].depth &&
+ kTextureFormatInfo[p.format].stencil &&
+ ((p.aspect0 === 'all' && p.type0 === 'sampled-texture') ||
+ (p.aspect1 === 'all' && p.type1 === 'sampled-texture'))
+ )
+ .unless(
+ p =>
+ // We can't set 'render-target' in bundle, so we need to exclude it from bundle.
+ p.binding1InBundle && p.type1 === 'render-target'
+ )
+ .unless(
+ p =>
+ // We can't set 'render-target' or bundle in compute. Note that type0 is definitely not
+ // 'render-target'
+ p.compute && (p.binding0InBundle || p.binding1InBundle || p.type1 === 'render-target')
+ )
+ .unless(
+ p =>
+ // Depth-stencil attachment views must encompass all aspects of the texture. Invalid
+ // cases are for depth-stencil textures when the aspect is not 'all'.
+ p.type1 === 'render-target' &&
+ kTextureFormatInfo[p.format].depth &&
+ kTextureFormatInfo[p.format].stencil &&
+ p.aspect1 !== 'all'
+ )
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(t => {
+ const {
+ compute,
+ binding0InBundle,
+ binding1InBundle,
+ format,
+ baseLevel,
+ baseLayer,
+ aspect0,
+ aspect1,
+ type0,
+ type1,
+ _resourceSuccess,
+ _usageSuccess,
+ } = t.params;
+
+ const texture = t.createTexture({
+ arrayLayerCount: TOTAL_LAYERS,
+ mipLevelCount: TOTAL_LEVELS,
+ format,
+ });
+
+ const view0 = texture.createView({
+ dimension: '2d',
+ baseMipLevel: BASE_LEVEL,
+ mipLevelCount: 1,
+ baseArrayLayer: BASE_LAYER,
+ arrayLayerCount: 1,
+ aspect: aspect0,
+ });
+
+ const view1 = texture.createView({
+ dimension: '2d',
+ baseMipLevel: baseLevel,
+ mipLevelCount: 1,
+ baseArrayLayer: baseLayer,
+ arrayLayerCount: 1,
+ aspect: aspect1,
+ });
+ const view1ResolvedFormat = kDepthStencilFormatResolvedAspect[format][aspect1];
+ const view1HasDepth = kTextureFormatInfo[view1ResolvedFormat].depth;
+ const view1HasStencil = kTextureFormatInfo[view1ResolvedFormat].stencil;
+
+ const encoder = t.device.createCommandEncoder();
+ // Color attachment's size should match depth/stencil attachment's size. Note that if
+ // type1 !== 'render-target' then there's no depthStencilAttachment to match anyway.
+ const depthStencilFormat = type1 === 'render-target' ? view1ResolvedFormat : undefined;
+
+ const size = SIZE >> baseLevel;
+ const pass = compute
+ ? encoder.beginComputePass()
+ : encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: t.createTexture({ width: size, height: size }).createView(),
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment: depthStencilFormat
+ ? {
+ view: view1,
+ depthStoreOp: view1HasDepth ? 'discard' : undefined,
+ depthLoadOp: view1HasDepth ? 'load' : undefined,
+ stencilStoreOp: view1HasStencil ? 'discard' : undefined,
+ stencilLoadOp: view1HasStencil ? 'load' : undefined,
+ }
+ : undefined,
+ });
+
+ const aspectSampleType = (format, aspect) => {
+ switch (aspect) {
+ case 'depth-only':
+ return 'depth';
+ case 'stencil-only':
+ return 'uint';
+ case 'all':
+ assert(kTextureFormatInfo[format].depth !== kTextureFormatInfo[format].stencil);
+ if (kTextureFormatInfo[format].stencil) {
+ return 'uint';
+ }
+ return 'depth';
+ }
+ };
+
+ // Create bind groups. Set bind groups in pass directly or set bind groups in bundle.
+ const bindGroup0 = t.createBindGroup(0, view0, type0, '2d', {
+ sampleType: type0 === 'sampled-texture' ? aspectSampleType(format, aspect0) : undefined,
+ });
+ if (binding0InBundle) {
+ assert(pass instanceof GPURenderPassEncoder);
+ t.createAndExecuteBundle(0, bindGroup0, pass, depthStencilFormat);
+ } else {
+ pass.setBindGroup(0, bindGroup0);
+ }
+ if (type1 !== 'render-target') {
+ const bindGroup1 = t.createBindGroup(1, view1, type1, '2d', {
+ sampleType: type1 === 'sampled-texture' ? aspectSampleType(format, aspect1) : undefined,
+ });
+ if (binding1InBundle) {
+ assert(pass instanceof GPURenderPassEncoder);
+ t.createAndExecuteBundle(1, bindGroup1, pass, depthStencilFormat);
+ } else {
+ pass.setBindGroup(1, bindGroup1);
+ }
+ }
+ if (compute) t.setComputePipelineAndCallDispatch(pass);
+ pass.end();
+
+ const disjointAspects =
+ (aspect0 === 'depth-only' && aspect1 === 'stencil-only') ||
+ (aspect0 === 'stencil-only' && aspect1 === 'depth-only');
+
+ // If subresources' mip/array slices has no overlap, or their binding types don't conflict,
+ // it will definitely success no matter what aspects they are binding to.
+ const success = disjointAspects || _resourceSuccess || _usageSuccess;
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('shader_stages_and_visibility,storage_write')
+ .desc(
+ `
+ Test that stage visibility doesn't affect resource usage validation.
+ - Use a texture as sampled, with 'readVisibility' {0,VERTEX,FRAGMENT,COMPUTE}
+ - Use a {same,different} texture as storage, with 'writeVisibility' {0,FRAGMENT,COMPUTE}
+
+ There should be a validation error IFF the same texture was used.
+ `
+ )
+ .params(u =>
+ u
+ .combine('compute', [false, true])
+ .beginSubcases()
+ .combine('secondUseConflicts', [false, true])
+ .combine('readVisibility', [
+ 0,
+ GPUConst.ShaderStage.VERTEX,
+ GPUConst.ShaderStage.FRAGMENT,
+ GPUConst.ShaderStage.COMPUTE,
+ ])
+ .combine('writeVisibility', [0, GPUConst.ShaderStage.FRAGMENT, GPUConst.ShaderStage.COMPUTE])
+ )
+ .fn(t => {
+ const { compute, readVisibility, writeVisibility, secondUseConflicts } = t.params;
+
+ const usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING;
+ const view = t.createTexture({ usage }).createView();
+ const view2 = secondUseConflicts ? view : t.createTexture({ usage }).createView();
+
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ { binding: 0, visibility: readVisibility, texture: {} },
+ {
+ binding: 1,
+ visibility: writeVisibility,
+ storageTexture: { access: 'write-only', format: 'rgba8unorm' },
+ },
+ ],
+ });
+ const bindGroup = t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ { binding: 0, resource: view },
+ { binding: 1, resource: view2 },
+ ],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ if (compute) {
+ const pass = encoder.beginComputePass();
+ pass.setBindGroup(0, bindGroup);
+
+ t.setComputePipelineAndCallDispatch(
+ pass,
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bgl],
+ })
+ );
+
+ pass.end();
+ } else {
+ const pass = t.beginSimpleRenderPass(encoder, t.createTexture().createView());
+ pass.setBindGroup(0, bindGroup);
+ pass.end();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, secondUseConflicts);
+ });
+
+g.test('shader_stages_and_visibility,attachment_write')
+ .desc(
+ `
+ Test that stage visibility doesn't affect resource usage validation.
+ - Use a texture as sampled, with 'readVisibility' {0,VERTEX,FRAGMENT,COMPUTE}
+ - Use a {same,different} texture as a render pass attachment
+
+ There should be a validation error IFF the same texture was used.
+ `
+ )
+ .params(u =>
+ u
+ .beginSubcases()
+ .combine('secondUseConflicts', [false, true])
+ .combine('readVisibility', [
+ 0,
+ GPUConst.ShaderStage.VERTEX,
+ GPUConst.ShaderStage.FRAGMENT,
+ GPUConst.ShaderStage.COMPUTE,
+ ])
+ )
+ .fn(t => {
+ const { readVisibility, secondUseConflicts } = t.params;
+
+ // writeonly-storage-texture binding type is not supported in vertex stage. So, this test
+ // uses writeonly-storage-texture binding as writable binding upon the same subresource if
+ // vertex stage is not included. Otherwise, it uses output attachment instead.
+ const usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT;
+
+ const view = t.createTexture({ usage }).createView();
+ const view2 = secondUseConflicts ? view : t.createTexture({ usage }).createView();
+ const bgl = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: readVisibility, texture: {} }],
+ });
+ const bindGroup = t.device.createBindGroup({
+ layout: bgl,
+ entries: [{ binding: 0, resource: view }],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = t.beginSimpleRenderPass(encoder, view2);
+ pass.setBindGroup(0, bindGroup);
+ pass.end();
+
+ // Texture usages in bindings with invisible shader stages should be validated. Invisible shader
+ // stages include shader stage with visibility none, compute shader stage in render pass, and
+ // vertex/fragment shader stage in compute pass.
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, secondUseConflicts);
+ });
+
+g.test('replaced_binding')
+ .desc(
+ `
+ Test whether a binding that's been replaced by another setBindGroup call can still
+ cause validation to fail (with a write/write conflict).
+ - In render pass, all setBindGroup calls contribute to the validation even if they're
+ shadowed.
+ - In compute pass, only the bindings visible at dispatchWorkgroups() contribute to validation.
+ `
+ )
+ .params(u =>
+ u
+ .combine('compute', [false, true])
+ .combine('callDrawOrDispatch', [false, true])
+ .combine('entry', [
+ { texture: {} },
+ { storageTexture: { access: 'write-only', format: 'rgba8unorm' } },
+ ])
+ )
+ .fn(t => {
+ const { compute, callDrawOrDispatch, entry } = t.params;
+
+ const sampledView = t.createTexture().createView();
+ const sampledStorageView = t
+ .createTexture({ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING })
+ .createView();
+
+ // Create bindGroup0. It has two bindings. These two bindings use different views/subresources.
+ const bglEntries0 = [
+ { binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: {} },
+ {
+ binding: 1,
+ visibility: GPUShaderStage.FRAGMENT,
+ ...entry,
+ },
+ ];
+
+ const bgEntries0 = [
+ { binding: 0, resource: sampledView },
+ { binding: 1, resource: sampledStorageView },
+ ];
+
+ const bindGroup0 = t.device.createBindGroup({
+ entries: bgEntries0,
+ layout: t.device.createBindGroupLayout({ entries: bglEntries0 }),
+ });
+
+ // Create bindGroup1. It has one binding, which use the same view/subresource of a binding in
+ // bindGroup0. So it may or may not conflicts with that binding in bindGroup0.
+ const bindGroup1 = t.createBindGroup(0, sampledStorageView, 'sampled-texture', '2d', undefined);
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = compute
+ ? encoder.beginComputePass()
+ : t.beginSimpleRenderPass(encoder, t.createTexture().createView());
+
+ // Set bindGroup0 and bindGroup1. bindGroup0 is replaced by bindGroup1 in the current pass.
+ // But bindings in bindGroup0 should be validated too.
+ pass.setBindGroup(0, bindGroup0);
+ if (callDrawOrDispatch) {
+ const pipeline = compute ? t.createNoOpComputePipeline() : t.createNoOpRenderPipeline();
+ t.setPipeline(pass, pipeline);
+ t.issueDrawOrDispatch(pass);
+ }
+ pass.setBindGroup(0, bindGroup1);
+ pass.end();
+
+ // MAINTENANCE_TODO: If the Compatible Usage List
+ // (https://gpuweb.github.io/gpuweb/#compatible-usage-list) gets programmatically defined in
+ // capability_info, use it here, instead of this logic, for clarity.
+ let success = entry.storageTexture?.access !== 'write-only';
+ // Replaced bindings should not be validated in compute pass, because validation only occurs
+ // inside dispatchWorkgroups() which only looks at the current resource usages.
+ success ||= compute;
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('bindings_in_bundle')
+ .desc(
+ `
+ Test the texture usages in bundles by using two bindings of the same texture with various
+ combination of {sampled, storage, render target} usages.
+ `
+ )
+ .params(u =>
+ u
+ .combine('type0', ['render-target', ...kTextureBindingTypes])
+ .combine('type1', ['render-target', ...kTextureBindingTypes])
+ .beginSubcases()
+ .combine('binding0InBundle', [false, true])
+ .combine('binding1InBundle', [false, true])
+ .expandWithParams(function* ({ type0, type1 }) {
+ const usageForType = type => {
+ switch (type) {
+ case 'multisampled-texture':
+ case 'sampled-texture':
+ return 'TEXTURE_BINDING';
+ case 'writeonly-storage-texture':
+ return 'STORAGE_BINDING';
+ case 'render-target':
+ return 'RENDER_ATTACHMENT';
+ }
+ };
+
+ yield {
+ _usage0: usageForType(type0),
+ _usage1: usageForType(type1),
+ _sampleCount:
+ type0 === 'multisampled-texture' || type1 === 'multisampled-texture' ? 4 : undefined,
+ };
+ })
+ .unless(
+ p =>
+ // We can't set 'render-target' in bundle, so we need to exclude it from bundle.
+ // In addition, if both bindings are non-bundle, there is no need to test it because
+ // we have far more comprehensive test cases for that situation in this file.
+ (p.binding0InBundle && p.type0 === 'render-target') ||
+ (p.binding1InBundle && p.type1 === 'render-target') ||
+ (!p.binding0InBundle && !p.binding1InBundle) ||
+ // Storage textures can't be multisampled.
+ (p._sampleCount !== undefined &&
+ p._sampleCount > 1 &&
+ (p._usage0 === 'STORAGE_BINDING' || p._usage1 === 'STORAGE_BINDING')) ||
+ // If both are sampled, we create two views of the same texture, so both must be
+ // multisampled.
+ (p.type0 === 'multisampled-texture' && p.type1 === 'sampled-texture') ||
+ (p.type0 === 'sampled-texture' && p.type1 === 'multisampled-texture')
+ )
+ )
+ .fn(t => {
+ const {
+ binding0InBundle,
+ binding1InBundle,
+ type0,
+ type1,
+ _usage0,
+ _usage1,
+ _sampleCount,
+ } = t.params;
+
+ // Two bindings are attached to the same texture view.
+ const usage =
+ _sampleCount === 4
+ ? GPUTextureUsage[_usage0] | GPUTextureUsage[_usage1] | GPUTextureUsage.RENDER_ATTACHMENT
+ : GPUTextureUsage[_usage0] | GPUTextureUsage[_usage1];
+ const view = t
+ .createTexture({
+ usage,
+ sampleCount: _sampleCount,
+ })
+ .createView();
+
+ const bindGroups = [];
+ if (type0 !== 'render-target') {
+ const binding0TexFormat = type0 === 'sampled-texture' ? undefined : 'rgba8unorm';
+ bindGroups[0] = t.createBindGroup(0, view, type0, '2d', { format: binding0TexFormat });
+ }
+ if (type1 !== 'render-target') {
+ const binding1TexFormat = type1 === 'sampled-texture' ? undefined : 'rgba8unorm';
+ bindGroups[1] = t.createBindGroup(1, view, type1, '2d', { format: binding1TexFormat });
+ }
+
+ const encoder = t.device.createCommandEncoder();
+ // At least one binding is in bundle, which means that its type is not 'render-target'.
+ // As a result, only one binding's type is 'render-target' at most.
+ const pass = t.beginSimpleRenderPass(
+ encoder,
+ type0 === 'render-target' || type1 === 'render-target' ? view : t.createTexture().createView()
+ );
+
+ const bindingsInBundle = [binding0InBundle, binding1InBundle];
+ for (let i = 0; i < 2; i++) {
+ // Create a bundle for each bind group if its bindings is required to be in bundle on purpose.
+ // Otherwise, call setBindGroup directly in pass if needed (when its binding is not
+ // 'render-target').
+ if (bindingsInBundle[i]) {
+ const bundleEncoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ });
+ bundleEncoder.setBindGroup(i, bindGroups[i]);
+ const bundleInPass = bundleEncoder.finish();
+ pass.executeBundles([bundleInPass]);
+ } else if (bindGroups[i] !== undefined) {
+ pass.setBindGroup(i, bindGroups[i]);
+ }
+ }
+
+ pass.end();
+
+ const isReadOnly = t => {
+ switch (t) {
+ case 'sampled-texture':
+ case 'multisampled-texture':
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ let success = false;
+ if (isReadOnly(type0) && isReadOnly(type1)) {
+ success = true;
+ }
+
+ if (type0 === 'writeonly-storage-texture' && type1 === 'writeonly-storage-texture') {
+ success = true;
+ }
+
+ // Resource usages in bundle should be validated.
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('unused_bindings_in_pipeline')
+ .desc(
+ `
+ Test that for compute pipelines with 'auto' layout, only bindings used by the pipeline count
+ toward the usage scope. For render passes, test the pipeline doesn't matter because only the
+ calls to setBindGroup count toward the usage scope.
+ `
+ )
+ .params(u =>
+ u
+ .combine('compute', [false, true])
+ .combine('useBindGroup0', [false, true])
+ .combine('useBindGroup1', [false, true])
+ .combine('setBindGroupsOrder', ['common', 'reversed'])
+ .combine('setPipeline', ['before', 'middle', 'after', 'none'])
+ .combine('callDrawOrDispatch', [false, true])
+ )
+ .fn(t => {
+ const {
+ compute,
+ useBindGroup0,
+ useBindGroup1,
+ setBindGroupsOrder,
+ setPipeline,
+ callDrawOrDispatch,
+ } = t.params;
+ const view = t
+ .createTexture({ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING })
+ .createView();
+ const bindGroup0 = t.createBindGroup(0, view, 'sampled-texture', '2d', {
+ format: 'rgba8unorm',
+ });
+ const bindGroup1 = t.createBindGroup(0, view, 'writeonly-storage-texture', '2d', {
+ format: 'rgba8unorm',
+ });
+
+ const wgslVertex = `@vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}`;
+ const wgslFragment = pp`
+ ${pp._if(useBindGroup0)}
+ @group(0) @binding(0) var image0 : texture_storage_2d<rgba8unorm, write>;
+ ${pp._endif}
+ ${pp._if(useBindGroup1)}
+ @group(1) @binding(0) var image1 : texture_storage_2d<rgba8unorm, write>;
+ ${pp._endif}
+ @fragment fn main() {}
+ `;
+
+ const wgslCompute = pp`
+ ${pp._if(useBindGroup0)}
+ @group(0) @binding(0) var image0 : texture_storage_2d<rgba8unorm, write>;
+ ${pp._endif}
+ ${pp._if(useBindGroup1)}
+ @group(1) @binding(0) var image1 : texture_storage_2d<rgba8unorm, write>;
+ ${pp._endif}
+ @compute @workgroup_size(1) fn main() {}
+ `;
+
+ const pipeline = compute
+ ? t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: wgslCompute,
+ }),
+ entryPoint: 'main',
+ },
+ })
+ : t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: wgslVertex,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: wgslFragment,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = compute
+ ? encoder.beginComputePass()
+ : encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: t.createTexture().createView(),
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ const index0 = setBindGroupsOrder === 'common' ? 0 : 1;
+ const index1 = setBindGroupsOrder === 'common' ? 1 : 0;
+ if (setPipeline === 'before') t.setPipeline(pass, pipeline);
+ pass.setBindGroup(index0, bindGroup0);
+ if (setPipeline === 'middle') t.setPipeline(pass, pipeline);
+ pass.setBindGroup(index1, bindGroup1);
+ if (setPipeline === 'after') t.setPipeline(pass, pipeline);
+ if (callDrawOrDispatch) t.issueDrawOrDispatch(pass);
+ pass.end();
+
+ // Resource usage validation scope is defined by the whole render pass or by dispatch calls.
+ // Regardless of whether or not dispatch is called, in a compute pass, we always succeed
+ // because in this test, none of the bindings are used by the pipeline.
+ // In a render pass, we always fail because usage is based on any bindings used in the
+ // render pass, regardless of whether the pipeline uses them.
+ let success = compute;
+
+ // Also fails if we try to draw/dispatch without a pipeline.
+ if (callDrawOrDispatch && setPipeline === 'none') {
+ success = false;
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('scope,dispatch')
+ .desc(
+ `
+ Tests that in a compute pass, no usage validation occurs without a dispatch call.
+ {Sets,skips} each of two conflicting bind groups in a pass {with,without} a dispatch call.
+ If both are set, AND there is a dispatch call, validation should fail.
+ `
+ )
+ .params(u =>
+ u
+ .combine('dispatch', ['none', 'direct', 'indirect'])
+ .beginSubcases()
+ .expand('setBindGroup0', p => (p.dispatch ? [true] : [false, true]))
+ .expand('setBindGroup1', p => (p.dispatch ? [true] : [false, true]))
+ )
+ .fn(t => {
+ const { dispatch, setBindGroup0, setBindGroup1 } = t.params;
+
+ const { bindGroup0, bindGroup1, encoder, pass, pipeline } = t.testValidationScope(true);
+ assert(pass instanceof GPUComputePassEncoder);
+ t.setPipeline(pass, pipeline);
+
+ if (setBindGroup0) pass.setBindGroup(0, bindGroup0);
+ if (setBindGroup1) pass.setBindGroup(1, bindGroup1);
+
+ switch (dispatch) {
+ case 'direct':
+ pass.dispatchWorkgroups(1);
+ break;
+ case 'indirect':
+ {
+ const indirectBuffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.INDIRECT });
+ pass.dispatchWorkgroupsIndirect(indirectBuffer, 0);
+ }
+ break;
+ }
+
+ pass.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, dispatch !== 'none' && setBindGroup0 && setBindGroup1);
+ });
+
+g.test('scope,basic,render')
+ .desc(
+ `
+ Tests that in a render pass, validation occurs even without a pipeline or draw call.
+ {Set,skip} each of two conflicting bind groups. If both are set, validation should fail.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('setBindGroup0', [false, true])
+ .combine('setBindGroup1', [false, true])
+ )
+ .fn(t => {
+ const { setBindGroup0, setBindGroup1 } = t.params;
+
+ const { bindGroup0, bindGroup1, encoder, pass } = t.testValidationScope(false);
+ assert(pass instanceof GPURenderPassEncoder);
+
+ if (setBindGroup0) pass.setBindGroup(0, bindGroup0);
+ if (setBindGroup1) pass.setBindGroup(1, bindGroup1);
+
+ pass.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, setBindGroup0 && setBindGroup1);
+ });
+
+g.test('scope,pass_boundary,compute')
+ .desc(
+ `
+ Test using two conflicting bind groups in separate dispatch calls, {with,without} a pass
+ boundary in between. This should always be valid.
+ `
+ )
+ .paramsSubcasesOnly(u => u.combine('splitPass', [false, true]))
+ .fn(t => {
+ const { splitPass } = t.params;
+
+ const { bindGroupLayouts, bindGroups } = t.makeConflictingBindGroups();
+
+ const encoder = t.device.createCommandEncoder();
+
+ const pipelineUsingBG0 = t.createNoOpComputePipeline(
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayouts[0]],
+ })
+ );
+
+ const pipelineUsingBG1 = t.createNoOpComputePipeline(
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayouts[1]],
+ })
+ );
+
+ let pass = encoder.beginComputePass();
+ pass.setPipeline(pipelineUsingBG0);
+ pass.setBindGroup(0, bindGroups[0]);
+ pass.dispatchWorkgroups(1);
+ if (splitPass) {
+ pass.end();
+ pass = encoder.beginComputePass();
+ }
+ pass.setPipeline(pipelineUsingBG1);
+ pass.setBindGroup(0, bindGroups[1]);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+
+ // Always valid
+ encoder.finish();
+ });
+
+g.test('scope,pass_boundary,render')
+ .desc(
+ `
+ Test using two conflicting bind groups in separate draw calls, {with,without} a pass
+ boundary in between. This should be valid only if there is a pass boundary.
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combine('splitPass', [false, true])
+ .combine('draw', [false, true])
+ )
+ .fn(t => {
+ const { splitPass, draw } = t.params;
+
+ const { bindGroupLayouts, bindGroups } = t.makeConflictingBindGroups();
+
+ const encoder = t.device.createCommandEncoder();
+
+ const pipelineUsingBG0 = t.createNoOpRenderPipeline(
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayouts[0]],
+ })
+ );
+
+ const pipelineUsingBG1 = t.createNoOpRenderPipeline(
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayouts[1]],
+ })
+ );
+
+ const attachment = t.createTexture().createView();
+
+ let pass = t.beginSimpleRenderPass(encoder, attachment);
+ pass.setPipeline(pipelineUsingBG0);
+ pass.setBindGroup(0, bindGroups[0]);
+ if (draw) pass.draw(3);
+ if (splitPass) {
+ pass.end();
+ pass = t.beginSimpleRenderPass(encoder, attachment);
+ }
+ pass.setPipeline(pipelineUsingBG1);
+ pass.setBindGroup(0, bindGroups[1]);
+ if (draw) pass.draw(3);
+ pass.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !splitPass);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js
new file mode 100644
index 0000000000..cbb676ca83
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_common.spec.js
@@ -0,0 +1,573 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Texture Usages Validation Tests in Same or Different Render Pass Encoders.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../../common/util/util.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ getColorAttachment(texture, textureViewDescriptor) {
+ const view = texture.createView(textureViewDescriptor);
+
+ return {
+ view,
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ };
+ }
+
+ createBindGroupForTest(textureView, textureUsage, sampleType) {
+ const bindGroupLayoutEntry = {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ };
+ switch (textureUsage) {
+ case 'texture':
+ bindGroupLayoutEntry.texture = { viewDimension: '2d-array', sampleType };
+ break;
+ case 'storage':
+ bindGroupLayoutEntry.storageTexture = {
+ access: 'write-only',
+ format: 'rgba8unorm',
+ viewDimension: '2d-array',
+ };
+ break;
+ default:
+ unreachable();
+ break;
+ }
+
+ const layout = this.device.createBindGroupLayout({
+ entries: [bindGroupLayoutEntry],
+ });
+ return this.device.createBindGroup({
+ layout,
+ entries: [{ binding: 0, resource: textureView }],
+ });
+ }
+
+ isRangeNotOverlapped(start0, end0, start1, end1) {
+ assert(start0 <= end0 && start1 <= end1);
+ // There are only two possibilities for two non-overlapped ranges:
+ // [start0, end0] [start1, end1] or
+ // [start1, end1] [start0, end0]
+ return end0 < start1 || end1 < start0;
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kTextureSize = 16;
+const kTextureLevels = 3;
+const kTextureLayers = 3;
+
+g.test('subresources,color_attachments')
+ .desc(
+ `
+ Test that the different subresource of the same texture are allowed to be used as color
+ attachments in same / different render pass encoder, while the same subresource is only allowed
+ to be used as different color attachments in different render pass encoders.`
+ )
+ .params(u =>
+ u
+ .combine('layer0', [0, 1])
+ .combine('level0', [0, 1])
+ .combine('layer1', [0, 1])
+ .combine('level1', [0, 1])
+ .combine('inSamePass', [true, false])
+ .unless(t => t.inSamePass && t.level0 !== t.level1)
+ )
+ .fn(async t => {
+ const { layer0, level0, layer1, level1, inSamePass } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ mipLevelCount: kTextureLevels,
+ });
+
+ const colorAttachment1 = t.getColorAttachment(texture, {
+ dimension: '2d',
+ baseArrayLayer: layer0,
+ arrayLayerCount: 1,
+ baseMipLevel: level0,
+ mipLevelCount: 1,
+ });
+ const colorAttachment2 = t.getColorAttachment(texture, {
+ dimension: '2d',
+ baseArrayLayer: layer1,
+ baseMipLevel: level1,
+ mipLevelCount: 1,
+ });
+ const encoder = t.device.createCommandEncoder();
+ if (inSamePass) {
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment1, colorAttachment2],
+ });
+ renderPass.end();
+ } else {
+ const renderPass1 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment1],
+ });
+ renderPass1.end();
+ const renderPass2 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment2],
+ });
+ renderPass2.end();
+ }
+
+ const success = inSamePass ? layer0 !== layer1 : true;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources,color_attachment_and_bind_group')
+ .desc(
+ `
+ Test that when one subresource of a texture is used as a color attachment, it cannot be used in a
+ bind group simultaneously in the same render pass encoder. It is allowed when the bind group is
+ used in another render pass encoder instead of the same one.`
+ )
+ .params(u =>
+ u
+ .combine('colorAttachmentLevel', [0, 1])
+ .combine('colorAttachmentLayer', [0, 1])
+ .combineWithParams([
+ { bgLevel: 0, bgLevelCount: 1 },
+ { bgLevel: 1, bgLevelCount: 1 },
+ { bgLevel: 1, bgLevelCount: 2 },
+ ])
+ .combineWithParams([
+ { bgLayer: 0, bgLayerCount: 1 },
+ { bgLayer: 1, bgLayerCount: 1 },
+ { bgLayer: 1, bgLayerCount: 2 },
+ ])
+ .combine('bgUsage', ['texture', 'storage'])
+ .unless(t => t.bgUsage === 'storage' && t.bgLevelCount > 1)
+ .combine('inSamePass', [true, false])
+ )
+ .fn(async t => {
+ const {
+ colorAttachmentLevel,
+ colorAttachmentLayer,
+ bgLevel,
+ bgLevelCount,
+ bgLayer,
+ bgLayerCount,
+ bgUsage,
+ inSamePass,
+ } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage:
+ GPUTextureUsage.RENDER_ATTACHMENT |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.STORAGE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ mipLevelCount: kTextureLevels,
+ });
+ const bindGroupView = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: bgLayer,
+ arrayLayerCount: bgLayerCount,
+ baseMipLevel: bgLevel,
+ mipLevelCount: bgLevelCount,
+ });
+ const bindGroup = t.createBindGroupForTest(bindGroupView, bgUsage, 'float');
+
+ const colorAttachment = t.getColorAttachment(texture, {
+ dimension: '2d',
+ baseArrayLayer: colorAttachmentLayer,
+ arrayLayerCount: 1,
+ baseMipLevel: colorAttachmentLevel,
+ mipLevelCount: 1,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment],
+ });
+ if (inSamePass) {
+ renderPass.setBindGroup(0, bindGroup);
+ renderPass.end();
+ } else {
+ renderPass.end();
+
+ const texture2 = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ mipLevelCount: 1,
+ });
+ const colorAttachment2 = t.getColorAttachment(texture2);
+ const renderPass2 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment2],
+ });
+ renderPass2.setBindGroup(0, bindGroup);
+ renderPass2.end();
+ }
+
+ const isMipLevelNotOverlapped = t.isRangeNotOverlapped(
+ colorAttachmentLevel,
+ colorAttachmentLevel,
+ bgLevel,
+ bgLevel + bgLevelCount - 1
+ );
+
+ const isArrayLayerNotOverlapped = t.isRangeNotOverlapped(
+ colorAttachmentLayer,
+ colorAttachmentLayer,
+ bgLayer,
+ bgLayer + bgLayerCount - 1
+ );
+
+ const isNotOverlapped = isMipLevelNotOverlapped || isArrayLayerNotOverlapped;
+
+ const success = inSamePass ? isNotOverlapped : true;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources,depth_stencil_attachment_and_bind_group')
+ .desc(
+ `
+ Test that when one subresource of a texture is used as a depth stencil attachment, it cannot be
+ used in a bind group simultaneously in the same render pass encoder. It is allowed when the bind
+ group is used in another render pass encoder instead of the same one, or the subresource is used
+ as a read-only depth stencil attachment.`
+ )
+ .params(u =>
+ u
+ .combine('dsLevel', [0, 1])
+ .combine('dsLayer', [0, 1])
+ .combineWithParams([
+ { bgLevel: 0, bgLevelCount: 1 },
+ { bgLevel: 1, bgLevelCount: 1 },
+ { bgLevel: 1, bgLevelCount: 2 },
+ ])
+ .combineWithParams([
+ { bgLayer: 0, bgLayerCount: 1 },
+ { bgLayer: 1, bgLayerCount: 1 },
+ { bgLayer: 1, bgLayerCount: 2 },
+ ])
+ .combine('dsReadOnly', [true, false])
+ .combine('bgAspect', ['depth-only', 'stencil-only'])
+ .combine('inSamePass', [true, false])
+ )
+ .fn(async t => {
+ const {
+ dsLevel,
+ dsLayer,
+ bgLevel,
+ bgLevelCount,
+ bgLayer,
+ bgLayerCount,
+ dsReadOnly,
+ bgAspect,
+ inSamePass,
+ } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'depth24plus-stencil8',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ mipLevelCount: kTextureLevels,
+ });
+ const bindGroupView = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: bgLayer,
+ arrayLayerCount: bgLayerCount,
+ baseMipLevel: bgLevel,
+ mipLevelCount: bgLevelCount,
+ aspect: bgAspect,
+ });
+ const sampleType = bgAspect === 'depth-only' ? 'depth' : 'uint';
+ const bindGroup = t.createBindGroupForTest(bindGroupView, 'texture', sampleType);
+
+ const attachmentView = texture.createView({
+ dimension: '2d',
+ baseArrayLayer: dsLayer,
+ arrayLayerCount: 1,
+ baseMipLevel: dsLevel,
+ mipLevelCount: 1,
+ });
+ const depthStencilAttachment = {
+ view: attachmentView,
+ depthReadOnly: dsReadOnly,
+ depthLoadOp: 'load',
+ depthStoreOp: 'store',
+ stencilReadOnly: dsReadOnly,
+ stencilLoadOp: 'load',
+ stencilStoreOp: 'store',
+ };
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment,
+ });
+ if (inSamePass) {
+ renderPass.setBindGroup(0, bindGroup);
+ renderPass.end();
+ } else {
+ renderPass.end();
+
+ const texture2 = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ mipLevelCount: 1,
+ });
+ const colorAttachment2 = t.getColorAttachment(texture2);
+ const renderPass2 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment2],
+ });
+ renderPass2.setBindGroup(0, bindGroup);
+ renderPass2.end();
+ }
+
+ const isMipLevelNotOverlapped = t.isRangeNotOverlapped(
+ dsLevel,
+ dsLevel,
+ bgLevel,
+ bgLevel + bgLevelCount - 1
+ );
+
+ const isArrayLayerNotOverlapped = t.isRangeNotOverlapped(
+ dsLayer,
+ dsLayer,
+ bgLayer,
+ bgLayer + bgLayerCount - 1
+ );
+
+ const isNotOverlapped = isMipLevelNotOverlapped || isArrayLayerNotOverlapped;
+
+ const success = !inSamePass || isNotOverlapped || dsReadOnly;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources,multiple_bind_groups')
+ .desc(
+ `
+ Test that when one color texture subresource is bound to different bind groups, its list of
+ internal usages within one usage scope can only be a compatible usage list. For texture
+ subresources in bind groups, the compatible usage lists are {TEXTURE_BINDING} and
+ {STORAGE_BINDING}, which means it can only be bound as both TEXTURE_BINDING and STORAGE_BINDING in
+ different render pass encoders, otherwise a validation error will occur.`
+ )
+ .params(u =>
+ u
+ .combine('bg0Levels', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('bg0Layers', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('bg1Levels', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('bg1Layers', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('bgUsage0', ['texture', 'storage'])
+ .combine('bgUsage1', ['texture', 'storage'])
+ .unless(
+ t =>
+ (t.bgUsage0 === 'storage' && t.bg0Levels.count > 1) ||
+ (t.bgUsage1 === 'storage' && t.bg1Levels.count > 1)
+ )
+ .combine('inSamePass', [true, false])
+ )
+ .fn(async t => {
+ const { bg0Levels, bg0Layers, bg1Levels, bg1Layers, bgUsage0, bgUsage1, inSamePass } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ mipLevelCount: kTextureLevels,
+ });
+ const bg0 = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: bg0Layers.base,
+ arrayLayerCount: bg0Layers.count,
+ baseMipLevel: bg0Levels.base,
+ mipLevelCount: bg0Levels.count,
+ });
+ const bg1 = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: bg1Layers.base,
+ arrayLayerCount: bg1Layers.count,
+ baseMipLevel: bg1Levels.base,
+ mipLevelCount: bg1Levels.count,
+ });
+ const bindGroup0 = t.createBindGroupForTest(bg0, bgUsage0, 'float');
+ const bindGroup1 = t.createBindGroupForTest(bg1, bgUsage1, 'float');
+
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ mipLevelCount: 1,
+ });
+ const colorAttachment = t.getColorAttachment(colorTexture);
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment],
+ });
+ if (inSamePass) {
+ renderPass.setBindGroup(0, bindGroup0);
+ renderPass.setBindGroup(1, bindGroup1);
+ renderPass.end();
+ } else {
+ renderPass.setBindGroup(0, bindGroup0);
+ renderPass.end();
+
+ const renderPass2 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment],
+ });
+ renderPass2.setBindGroup(1, bindGroup1);
+ renderPass2.end();
+ }
+
+ const isMipLevelNotOverlapped = t.isRangeNotOverlapped(
+ bg0Levels.base,
+ bg0Levels.base + bg0Levels.count - 1,
+ bg1Levels.base,
+ bg1Levels.base + bg1Levels.count - 1
+ );
+
+ const isArrayLayerNotOverlapped = t.isRangeNotOverlapped(
+ bg0Layers.base,
+ bg0Layers.base + bg0Layers.count - 1,
+ bg1Layers.base,
+ bg1Layers.base + bg1Layers.count - 1
+ );
+
+ const isNotOverlapped = isMipLevelNotOverlapped || isArrayLayerNotOverlapped;
+
+ const success = !inSamePass || isNotOverlapped || bgUsage0 === bgUsage1;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources,depth_stencil_texture_in_bind_groups')
+ .desc(
+ `
+ Test that when one depth stencil texture subresource is bound to different bind groups, we can
+ always bind these two bind groups in either the same or different render pass encoder as the depth
+ stencil texture can only be bound as TEXTURE_BINDING in the bind group.`
+ )
+ .params(u =>
+ u
+ .combine('view0Levels', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('view0Layers', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('view1Levels', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('view1Layers', [
+ { base: 0, count: 1 },
+ { base: 1, count: 1 },
+ { base: 1, count: 2 },
+ ])
+ .combine('aspect0', ['depth-only', 'stencil-only'])
+ .combine('aspect1', ['depth-only', 'stencil-only'])
+ .combine('inSamePass', [true, false])
+ )
+ .fn(async t => {
+ const {
+ view0Levels,
+ view0Layers,
+ view1Levels,
+ view1Layers,
+ aspect0,
+ aspect1,
+ inSamePass,
+ } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'depth24plus-stencil8',
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ mipLevelCount: kTextureLevels,
+ });
+ const bindGroupView0 = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: view0Layers.base,
+ arrayLayerCount: view0Layers.count,
+ baseMipLevel: view0Levels.base,
+ mipLevelCount: view0Levels.count,
+ aspect: aspect0,
+ });
+ const bindGroupView1 = texture.createView({
+ dimension: '2d-array',
+ baseArrayLayer: view1Layers.base,
+ arrayLayerCount: view1Layers.count,
+ baseMipLevel: view1Levels.base,
+ mipLevelCount: view1Levels.count,
+ aspect: aspect1,
+ });
+
+ const sampleType0 = aspect0 === 'depth-only' ? 'depth' : 'uint';
+ const sampleType1 = aspect1 === 'depth-only' ? 'depth' : 'uint';
+ const bindGroup0 = t.createBindGroupForTest(bindGroupView0, 'texture', sampleType0);
+ const bindGroup1 = t.createBindGroupForTest(bindGroupView1, 'texture', sampleType1);
+
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ mipLevelCount: 1,
+ });
+ const colorAttachment = t.getColorAttachment(colorTexture);
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment],
+ });
+ if (inSamePass) {
+ renderPass.setBindGroup(0, bindGroup0);
+ renderPass.setBindGroup(1, bindGroup1);
+ renderPass.end();
+ } else {
+ renderPass.setBindGroup(0, bindGroup0);
+ renderPass.end();
+
+ const renderPass2 = encoder.beginRenderPass({
+ colorAttachments: [colorAttachment],
+ });
+ renderPass2.setBindGroup(1, bindGroup1);
+ renderPass2.end();
+ }
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js
new file mode 100644
index 0000000000..9d11eaa1c2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/resource_usages/texture/in_render_misc.spec.js
@@ -0,0 +1,403 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Texture Usages Validation Tests on All Kinds of WebGPU Subresource Usage Scopes.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../../common/util/util.js';
+import { ValidationTest } from '../../validation_test.js';
+
+class F extends ValidationTest {
+ createBindGroupLayoutForTest(textureUsage, sampleType, visibility = GPUShaderStage['FRAGMENT']) {
+ const bindGroupLayoutEntry = {
+ binding: 0,
+ visibility,
+ };
+
+ switch (textureUsage) {
+ case 'texture':
+ bindGroupLayoutEntry.texture = { viewDimension: '2d-array', sampleType };
+ break;
+ case 'storage':
+ bindGroupLayoutEntry.storageTexture = {
+ access: 'write-only',
+ format: 'rgba8unorm',
+ viewDimension: '2d-array',
+ };
+ break;
+ default:
+ unreachable();
+ break;
+ }
+
+ return this.device.createBindGroupLayout({
+ entries: [bindGroupLayoutEntry],
+ });
+ }
+
+ createBindGroupForTest(
+ textureView,
+ textureUsage,
+ sampleType,
+ visibility = GPUShaderStage['FRAGMENT']
+ ) {
+ return this.device.createBindGroup({
+ layout: this.createBindGroupLayoutForTest(textureUsage, sampleType, visibility),
+ entries: [{ binding: 0, resource: textureView }],
+ });
+ }
+}
+
+export const g = makeTestGroup(F);
+
+const kTextureSize = 16;
+const kTextureLayers = 3;
+
+g.test('subresources,set_bind_group_on_same_index_color_texture')
+ .desc(
+ `
+ Test that when one color texture subresource is bound to different bind groups, whether the bind
+ groups are reset by another compatible ones or not, its list of internal usages within one usage
+ scope can only be a compatible usage list.`
+ )
+ .params(u =>
+ u
+ .combineWithParams([
+ { useDifferentTextureAsTexture2: true, baseLayer2: 0, view2Binding: 'texture' },
+ { useDifferentTextureAsTexture2: false, baseLayer2: 0, view2Binding: 'texture' },
+ { useDifferentTextureAsTexture2: false, baseLayer2: 1, view2Binding: 'texture' },
+ { useDifferentTextureAsTexture2: false, baseLayer2: 0, view2Binding: 'storage' },
+ { useDifferentTextureAsTexture2: false, baseLayer2: 1, view2Binding: 'storage' },
+ ])
+ .combine('hasConflict', [true, false])
+ )
+ .fn(async t => {
+ const { useDifferentTextureAsTexture2, baseLayer2, view2Binding, hasConflict } = t.params;
+
+ const texture0 = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ });
+ // We always bind the first layer of the texture to bindGroup0.
+ const textureView0 = texture0.createView({
+ dimension: '2d-array',
+ baseArrayLayer: 0,
+ arrayLayerCount: 1,
+ });
+ const bindGroup0 = t.createBindGroupForTest(textureView0, view2Binding, 'float');
+
+ // In one renderPassEncoder it is an error to set both bindGroup0 and bindGroup1.
+ const view1Binding = hasConflict
+ ? view2Binding === 'texture'
+ ? 'storage'
+ : 'texture'
+ : view2Binding;
+ const bindGroup1 = t.createBindGroupForTest(textureView0, view1Binding, 'float');
+
+ const texture2 = useDifferentTextureAsTexture2
+ ? t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ })
+ : texture0;
+ const textureView2 = texture2.createView({
+ dimension: '2d-array',
+ baseArrayLayer: baseLayer2,
+ arrayLayerCount: kTextureLayers - baseLayer2,
+ });
+ // There should be no conflict between bindGroup0 and validBindGroup2.
+ const validBindGroup2 = t.createBindGroupForTest(textureView2, view2Binding, 'float');
+
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPassEncoder.setBindGroup(0, bindGroup0);
+ renderPassEncoder.setBindGroup(1, bindGroup1);
+ renderPassEncoder.setBindGroup(1, validBindGroup2);
+ renderPassEncoder.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, hasConflict);
+ });
+
+g.test('subresources,set_bind_group_on_same_index_depth_stencil_texture')
+ .desc(
+ `
+ Test that when one depth stencil texture subresource is bound to different bind groups, whether
+ the bind groups are reset by another compatible ones or not, its list of internal usages within
+ one usage scope can only be a compatible usage list.`
+ )
+ .params(u =>
+ u
+ .combine('bindAspect', ['depth-only', 'stencil-only'])
+ .combine('depthStencilReadOnly', [true, false])
+ )
+ .fn(async t => {
+ const { bindAspect, depthStencilReadOnly } = t.params;
+ const depthStencilTexture = t.device.createTexture({
+ format: 'depth24plus-stencil8',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+
+ const conflictedToNonReadOnlyAttachmentBindGroup = t.createBindGroupForTest(
+ depthStencilTexture.createView({
+ dimension: '2d-array',
+ aspect: bindAspect,
+ }),
+ 'texture',
+ bindAspect === 'depth-only' ? 'depth' : 'uint'
+ );
+
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+ const validBindGroup = t.createBindGroupForTest(
+ colorTexture.createView({
+ dimension: '2d-array',
+ }),
+ 'texture',
+ 'float'
+ );
+
+ const encoder = t.device.createCommandEncoder();
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ view: depthStencilTexture.createView(),
+ depthReadOnly: depthStencilReadOnly,
+ stencilReadOnly: depthStencilReadOnly,
+ },
+ });
+ renderPassEncoder.setBindGroup(0, conflictedToNonReadOnlyAttachmentBindGroup);
+ renderPassEncoder.setBindGroup(0, validBindGroup);
+ renderPassEncoder.end();
+
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !depthStencilReadOnly);
+ });
+
+g.test('subresources,set_unused_bind_group')
+ .desc(
+ `
+ Test that when one texture subresource is bound to different bind groups and the bind groups are
+ used in the same render or compute pass encoder, its list of internal usages within one usage
+ scope can only be a compatible usage list.`
+ )
+ .params(u => u.combine('inRenderPass', [true, false]).combine('hasConflict', [true, false]))
+ .fn(async t => {
+ const { inRenderPass, hasConflict } = t.params;
+
+ const texture0 = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
+ size: [kTextureSize, kTextureSize, kTextureLayers],
+ });
+ // We always bind the first layer of the texture to bindGroup0.
+ const textureView0 = texture0.createView({
+ dimension: '2d-array',
+ baseArrayLayer: 0,
+ arrayLayerCount: 1,
+ });
+ const visibility = inRenderPass ? GPUShaderStage.FRAGMENT : GPUShaderStage.COMPUTE;
+ // bindGroup0 is used by the pipelines, and bindGroup1 is not used by the pipelines.
+ const textureUsage0 = inRenderPass ? 'texture' : 'storage';
+ const textureUsage1 = hasConflict ? (inRenderPass ? 'storage' : 'texture') : textureUsage0;
+ const bindGroup0 = t.createBindGroupForTest(textureView0, textureUsage0, 'float', visibility);
+ const bindGroup1 = t.createBindGroupForTest(textureView0, textureUsage1, 'float', visibility);
+
+ const encoder = t.device.createCommandEncoder();
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [t.createBindGroupLayoutForTest(textureUsage0, 'float', visibility)],
+ });
+ if (inRenderPass) {
+ const renderPipeline = t.device.createRenderPipeline({
+ layout: pipelineLayout,
+ vertex: {
+ module: t.device.createShaderModule({
+ code: t.getNoOpShaderCode('VERTEX'),
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var texture0 : texture_2d_array<f32>;
+ @fragment fn main()
+ -> @location(0) vec4<f32> {
+ return textureLoad(texture0, vec2<i32>(), 0, 0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ loadOp: 'load',
+ storeOp: 'store',
+ },
+ ],
+ });
+ renderPassEncoder.setBindGroup(0, bindGroup0);
+ renderPassEncoder.setBindGroup(1, bindGroup1);
+ renderPassEncoder.setPipeline(renderPipeline);
+ renderPassEncoder.draw(1);
+ renderPassEncoder.end();
+ } else {
+ const computePipeline = t.device.createComputePipeline({
+ layout: pipelineLayout,
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var texture0 : texture_storage_2d_array<rgba8unorm, write>;
+ @compute @workgroup_size(1)
+ fn main() {
+ textureStore(texture0, vec2<i32>(), 0, vec4<f32>());
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ const computePassEncoder = encoder.beginComputePass();
+ computePassEncoder.setBindGroup(0, bindGroup0);
+ computePassEncoder.setBindGroup(1, bindGroup1);
+ computePassEncoder.setPipeline(computePipeline);
+ computePassEncoder.dispatchWorkgroups(1);
+ computePassEncoder.end();
+ }
+
+ // In WebGPU SPEC (Chapter 3.4.5, Synchronization):
+ // This specification defines the following usage scopes:
+ // - In a compute pass, each dispatch command (dispatchWorkgroups() or
+ // dispatchWorkgroupsIndirect()) is one usage scope. A subresource is "used" in the usage
+ // scope if it is potentially accessible by the command. State-setting compute pass commands,
+ // like setBindGroup(index, bindGroup, dynamicOffsets), do not contribute directly to a usage
+ // scope.
+ // - One render pass is one usage scope. A subresource is "used" in the usage scope if it’s
+ // referenced by any (state-setting or non-state-setting) command. For example, in
+ // setBindGroup(index, bindGroup, dynamicOffsets), every subresource in bindGroup is "used" in
+ // the render pass’s usage scope.
+ const success = !inRenderPass || !hasConflict;
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, !success);
+ });
+
+g.test('subresources,texture_usages_in_copy_and_render_pass')
+ .desc(
+ `
+ Test that using one texture subresource in a render pass encoder and a copy command is always
+ allowed as WebGPU SPEC (chapter 3.4.5) defines that out of any pass encoder, each command always
+ belongs to one usage scope.`
+ )
+ .params(u =>
+ u
+ .combine('usage0', ['copy-src', 'copy-dst', 'texture', 'storage', 'color-attachment'])
+ .combine('usage1', ['copy-src', 'copy-dst', 'texture', 'storage', 'color-attachment'])
+ .filter(
+ ({ usage0, usage1 }) =>
+ usage0 === 'copy-src' ||
+ usage0 === 'copy-dst' ||
+ usage1 === 'copy-src' ||
+ usage1 === 'copy-dst'
+ )
+ )
+ .fn(async t => {
+ const { usage0, usage1 } = t.params;
+
+ const texture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.STORAGE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+
+ const UseTextureOnCommandEncoder = (texture, usage, encoder) => {
+ switch (usage) {
+ case 'copy-src': {
+ const buffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ encoder.copyTextureToBuffer({ texture }, { buffer }, [1, 1, 1]);
+ break;
+ }
+ case 'copy-dst': {
+ const buffer = t.createBufferWithState('valid', {
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ encoder.copyBufferToTexture({ buffer }, { texture }, [1, 1, 1]);
+ break;
+ }
+ case 'color-attachment': {
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [{ view: texture.createView(), loadOp: 'load', storeOp: 'store' }],
+ });
+ renderPassEncoder.end();
+ break;
+ }
+ case 'texture':
+ case 'storage': {
+ const colorTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ size: [kTextureSize, kTextureSize, 1],
+ });
+ const renderPassEncoder = encoder.beginRenderPass({
+ colorAttachments: [
+ { view: colorTexture.createView(), loadOp: 'load', storeOp: 'store' },
+ ],
+ });
+ const bindGroup = t.createBindGroupForTest(
+ texture.createView({
+ dimension: '2d-array',
+ }),
+ usage,
+ 'float'
+ );
+
+ renderPassEncoder.setBindGroup(0, bindGroup);
+ renderPassEncoder.end();
+ break;
+ }
+ }
+ };
+ const encoder = t.device.createCommandEncoder();
+ UseTextureOnCommandEncoder(texture, usage0, encoder);
+ UseTextureOnCommandEncoder(texture, usage1, encoder);
+ t.expectValidationError(() => {
+ encoder.finish();
+ }, false);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js
new file mode 100644
index 0000000000..ad3c3807d3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/entry_point.spec.js
@@ -0,0 +1,118 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This tests entry point validation of compute/render pipelines and their shader modules.
+
+The entryPoint in shader module include standard "main" and others.
+The entryPoint assigned in descriptor include:
+- Matching case (control case)
+- Empty string
+- Mistyping
+- Containing invalid char, including space and control codes (Null character)
+- Unicode entrypoints and their ASCIIfied version
+
+TODO:
+- Test unicode normalization (gpuweb/gpuweb#1160)
+- Fine-tune test cases to reduce number by removing trivially similiar cases
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kDefaultVertexShaderCode, getShaderWithEntryPoint } from '../../../util/shader.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+const kEntryPointTestCases = [
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'main' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: '' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'main\0' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'main\0a' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'mian' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'main ' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'ma in' },
+ { shaderModuleEntryPoint: 'main', stageEntryPoint: 'main\n' },
+ { shaderModuleEntryPoint: 'mian', stageEntryPoint: 'mian' },
+ { shaderModuleEntryPoint: 'mian', stageEntryPoint: 'main' },
+ { shaderModuleEntryPoint: 'mainmain', stageEntryPoint: 'mainmain' },
+ { shaderModuleEntryPoint: 'mainmain', stageEntryPoint: 'foo' },
+ { shaderModuleEntryPoint: 'main_t12V3', stageEntryPoint: 'main_t12V3' },
+ { shaderModuleEntryPoint: 'main_t12V3', stageEntryPoint: 'main_t12V5' },
+ { shaderModuleEntryPoint: 'main_t12V3', stageEntryPoint: '_main_t12V3' },
+ { shaderModuleEntryPoint: 'séquençage', stageEntryPoint: 'séquençage' },
+ { shaderModuleEntryPoint: 'séquençage', stageEntryPoint: 'sequencage' },
+];
+
+g.test('compute')
+ .desc(
+ `
+Tests calling createComputePipeline(Async) with valid vertex stage shader and different entryPoints,
+and check that the APIs only accept matching entryPoint.
+`
+ )
+ .params(u => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases))
+ .fn(async t => {
+ const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params;
+ const descriptor = {
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: getShaderWithEntryPoint('compute', shaderModuleEntryPoint),
+ }),
+ entryPoint: stageEntryPoint,
+ },
+ };
+ const _success = shaderModuleEntryPoint === stageEntryPoint;
+ t.doCreateComputePipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('vertex')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) with valid vertex stage shader and different entryPoints,
+and check that the APIs only accept matching entryPoint.
+`
+ )
+ .params(u => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases))
+ .fn(async t => {
+ const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params;
+ const descriptor = {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: getShaderWithEntryPoint('vertex', shaderModuleEntryPoint),
+ }),
+ entryPoint: stageEntryPoint,
+ },
+ };
+ const _success = shaderModuleEntryPoint === stageEntryPoint;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
+
+g.test('fragment')
+ .desc(
+ `
+Tests calling createRenderPipeline(Async) with valid fragment stage shader and different entryPoints,
+and check that the APIs only accept matching entryPoint.
+`
+ )
+ .params(u => u.combine('isAsync', [true, false]).combineWithParams(kEntryPointTestCases))
+ .fn(async t => {
+ const { isAsync, shaderModuleEntryPoint, stageEntryPoint } = t.params;
+ const descriptor = {
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: kDefaultVertexShaderCode,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: getShaderWithEntryPoint('fragment', shaderModuleEntryPoint),
+ }),
+ entryPoint: stageEntryPoint,
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ };
+ const _success = shaderModuleEntryPoint === stageEntryPoint;
+ t.doCreateRenderPipelineTest(isAsync, _success, descriptor);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/overrides.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/overrides.spec.js
new file mode 100644
index 0000000000..dc2972968d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/shader_module/overrides.spec.js
@@ -0,0 +1,97 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+This tests overrides numeric identifiers should not conflict.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('id_conflict')
+ .desc(
+ `
+Tests that overrides' explicit numeric identifier should not conflict.
+`
+ )
+ .fn(async t => {
+ t.expectValidationError(() => {
+ t.device.createShaderModule({
+ code: `
+@id(1234) override c0: u32;
+@id(4321) override c1: u32;
+
+@compute @workgroup_size(1) fn main() {
+ // make sure the overridable constants are not optimized out
+ _ = c0;
+ _ = c1;
+}
+ `,
+ });
+ }, false);
+
+ t.expectValidationError(() => {
+ t.device.createShaderModule({
+ code: `
+@id(1234) override c0: u32;
+@id(1234) override c1: u32;
+
+@compute @workgroup_size(1) fn main() {
+ // make sure the overridable constants are not optimized out
+ _ = c0;
+ _ = c1;
+}
+ `,
+ });
+ }, true);
+ });
+
+g.test('name_conflict')
+ .desc(
+ `
+Tests that overrides' variable name should not conflict, regardless of their numeric identifiers.
+`
+ )
+ .fn(async t => {
+ t.expectValidationError(() => {
+ t.device.createShaderModule({
+ code: `
+override c0: u32;
+override c0: u32;
+
+@compute @workgroup_size(1) fn main() {
+ // make sure the overridable constants are not optimized out
+ _ = c0;
+}
+ `,
+ });
+ }, true);
+
+ t.expectValidationError(() => {
+ t.device.createShaderModule({
+ code: `
+@id(1) override c0: u32;
+override c0: u32;
+
+@compute @workgroup_size(1) fn main() {
+ // make sure the overridable constants are not optimized out
+ _ = c0;
+}
+ `,
+ });
+ }, true);
+
+ t.expectValidationError(() => {
+ t.device.createShaderModule({
+ code: `
+@id(1) override c0: u32;
+@id(2) override c0: u32;
+
+@compute @workgroup_size(1) fn main() {
+ // make sure the overridable constants are not optimized out
+ _ = c0;
+}
+ `,
+ });
+ }, true);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js
new file mode 100644
index 0000000000..5897085b6d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/state/device_lost/destroy.spec.js
@@ -0,0 +1,957 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for device lost induced via destroy.
+ - Tests that prior to device destruction, valid APIs do not generate errors (control case).
+ - After device destruction, runs the same APIs. No expected observable results, so test crash or future failures are the only current failure indicators.
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import {
+ allBindingEntries,
+ bindingTypeInfo,
+ kBindableResources,
+ kBufferUsageKeys,
+ kBufferUsageInfo,
+ kBufferUsageCopy,
+ kBufferUsageCopyInfo,
+ kCompressedTextureFormats,
+ kQueryTypes,
+ kTextureUsageType,
+ kTextureUsageTypeInfo,
+ kTextureUsageCopy,
+ kTextureUsageCopyInfo,
+ kRegularTextureFormats,
+ kRenderableColorTextureFormats,
+ kShaderStageKeys,
+ kTextureFormatInfo,
+} from '../../../../capability_info.js';
+
+import {
+ canCopyFromCanvasContext,
+ createCanvas,
+ kAllCanvasTypes,
+ kValidCanvasContextIds,
+} from '../../../../util/create_elements.js';
+import { ValidationTest } from '../../validation_test.js';
+
+const kCommandValidationStages = ['finish', 'submit'];
+
+class DeviceDestroyTests extends ValidationTest {
+ /**
+ * Expects that `fn` does not produce any errors before the device is destroyed, and then calls
+ * `fn` after the device is destroyed without any specific expectation. If `awaitLost` is true, we
+ * also wait for device.lost to resolve before executing `fn` in the destroy case.
+ */
+ async executeAfterDestroy(fn, awaitLost) {
+ this.expectDeviceLost('destroyed');
+
+ this.expectValidationError(fn, false);
+ this.device.destroy();
+ if (awaitLost) {
+ const lostInfo = await this.device.lost;
+ this.expect(lostInfo.reason === 'destroyed');
+ }
+ fn();
+ }
+
+ /**
+ * Expects that encoders can finish and submit the resulting commands before the device is
+ * destroyed, then repeats the same process after the device is destroyed without any specific
+ * expectations.
+ * There are two valid stages: 'finish' and 'submit'.
+ * 'finish': Tests [encode, finish] and [encoder, destroy, finish]
+ * 'submit': Tests [encoder, finish, submit] and [encoder, finish, destroy, submit]
+ */
+ async executeCommandsAfterDestroy(stage, awaitLost, encoderType, fn) {
+ this.expectDeviceLost('destroyed');
+
+ switch (stage) {
+ case 'finish': {
+ // Control case
+ fn(this.createEncoder(encoderType)).validateFinish(true);
+ // Validation case
+ const encoder = fn(this.createEncoder(encoderType));
+ await this.executeAfterDestroy(() => {
+ encoder.finish();
+ }, awaitLost);
+ break;
+ }
+ case 'submit': {
+ // Control case
+ fn(this.createEncoder(encoderType)).validateFinishAndSubmit(true, true);
+ // Validation case
+ const commands = fn(this.createEncoder(encoderType)).validateFinish(true);
+ await this.executeAfterDestroy(() => {
+ this.queue.submit([commands]);
+ }, awaitLost);
+ break;
+ }
+ }
+ }
+}
+
+export const g = makeTestGroup(DeviceDestroyTests);
+
+g.test('createBuffer')
+ .desc(
+ `
+Tests creating buffers on destroyed device. Tests valid combinations of:
+ - Various usages
+ - Mapped at creation or not
+ `
+ )
+ .params(u =>
+ u
+ .combine('usageType', kBufferUsageKeys)
+ .beginSubcases()
+ .combine('usageCopy', kBufferUsageCopy)
+ .combine('awaitLost', [true, false])
+ .filter(({ usageType, usageCopy }) => {
+ if (usageType === 'COPY_SRC' || usageType === 'COPY_DST') {
+ return false;
+ }
+ if (usageType === 'MAP_READ') {
+ return usageCopy === 'COPY_NONE' || usageCopy === 'COPY_DST';
+ }
+ if (usageType === 'MAP_WRITE') {
+ return usageCopy === 'COPY_NONE' || usageCopy === 'COPY_SRC';
+ }
+ return true;
+ })
+ .combine('mappedAtCreation', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, usageType, usageCopy, mappedAtCreation } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createBuffer({
+ size: 16,
+ usage: kBufferUsageInfo[usageType] | kBufferUsageCopyInfo[usageCopy],
+ mappedAtCreation,
+ });
+ }, awaitLost);
+ });
+
+g.test('createTexture,2d,uncompressed_format')
+ .desc(
+ `
+Tests creating 2d uncompressed textures on destroyed device. Tests valid combinations of:
+ - Various uncompressed texture formats
+ - Various usages
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRegularTextureFormats)
+ .beginSubcases()
+ .combine('usageType', kTextureUsageType)
+ .combine('usageCopy', kTextureUsageCopy)
+ .combine('awaitLost', [true, false])
+ .filter(({ format, usageType }) => {
+ const info = kTextureFormatInfo[format];
+ return !(
+ (!info.renderable && usageType === 'render') ||
+ (!info.storage && usageType === 'storage')
+ );
+ })
+ )
+ .fn(async t => {
+ const { awaitLost, format, usageType, usageCopy } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+ await t.executeAfterDestroy(() => {
+ t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: kTextureUsageTypeInfo[usageType] | kTextureUsageCopyInfo[usageCopy],
+ format,
+ });
+ }, awaitLost);
+ });
+
+g.test('createTexture,2d,compressed_format')
+ .desc(
+ `
+Tests creating 2d compressed textures on destroyed device. Tests valid combinations of:
+ - Various compressed texture formats
+ - Various usages
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kCompressedTextureFormats)
+ .beginSubcases()
+ .combine('usageType', kTextureUsageType)
+ .combine('usageCopy', kTextureUsageCopy)
+ .combine('awaitLost', [true, false])
+ .filter(({ format, usageType }) => {
+ const info = kTextureFormatInfo[format];
+ return !(
+ (!info.renderable && usageType === 'render') ||
+ (!info.storage && usageType === 'storage')
+ );
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { awaitLost, format, usageType, usageCopy } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+ await t.executeAfterDestroy(() => {
+ t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: kTextureUsageTypeInfo[usageType] | kTextureUsageCopyInfo[usageCopy],
+ format,
+ });
+ }, awaitLost);
+ });
+
+g.test('createView,2d,uncompressed_format')
+ .desc(
+ `
+Tests creating texture views on 2d uncompressed textures from destroyed device. Tests valid combinations of:
+ - Various uncompressed texture formats
+ - Various usages
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRegularTextureFormats)
+ .beginSubcases()
+ .combine('usageType', kTextureUsageType)
+ .combine('usageCopy', kTextureUsageCopy)
+ .combine('awaitLost', [true, false])
+ .filter(({ format, usageType }) => {
+ const info = kTextureFormatInfo[format];
+ return !(
+ (!info.renderable && usageType === 'render') ||
+ (!info.storage && usageType === 'storage')
+ );
+ })
+ )
+ .fn(async t => {
+ const { awaitLost, format, usageType, usageCopy } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+ const texture = t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: kTextureUsageTypeInfo[usageType] | kTextureUsageCopyInfo[usageCopy],
+ format,
+ });
+ await t.executeAfterDestroy(() => {
+ texture.createView({ format });
+ }, awaitLost);
+ });
+
+g.test('createView,2d,compressed_format')
+ .desc(
+ `
+Tests creating texture views on 2d compressed textures from destroyed device. Tests valid combinations of:
+ - Various compressed texture formats
+ - Various usages
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kCompressedTextureFormats)
+ .beginSubcases()
+ .combine('usageType', kTextureUsageType)
+ .combine('usageCopy', kTextureUsageCopy)
+ .combine('awaitLost', [true, false])
+ .filter(({ format, usageType }) => {
+ const info = kTextureFormatInfo[format];
+ return !(
+ (!info.renderable && usageType === 'render') ||
+ (!info.storage && usageType === 'storage')
+ );
+ })
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { awaitLost, format, usageType, usageCopy } = t.params;
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+ const texture = t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: kTextureUsageTypeInfo[usageType] | kTextureUsageCopyInfo[usageCopy],
+ format,
+ });
+ await t.executeAfterDestroy(() => {
+ texture.createView({ format });
+ }, awaitLost);
+ });
+
+g.test('createSampler')
+ .desc(
+ `
+Tests creating samplers on destroyed device.
+ `
+ )
+ .params(u => u.beginSubcases().combine('awaitLost', [true, false]))
+ .fn(async t => {
+ const { awaitLost } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createSampler();
+ }, awaitLost);
+ });
+
+g.test('createBindGroupLayout')
+ .desc(
+ `
+Tests creating bind group layouts on destroyed device. Tests valid combinations of:
+ - Various valid binding entries
+ - Maximum set of visibility for each binding entry
+ `
+ )
+ .params(u =>
+ u.combine('entry', allBindingEntries(false)).beginSubcases().combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, entry } = t.params;
+ const visibility = bindingTypeInfo(entry).validStages;
+ await t.executeAfterDestroy(() => {
+ t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility, ...entry }],
+ });
+ }, awaitLost);
+ });
+
+g.test('createBindGroup')
+ .desc(
+ `
+Tests creating bind group on destroyed device. Tests valid combinations of:
+ - Various binded resource types
+ - Various valid binding entries
+ - Maximum set of visibility for each binding entry
+ `
+ )
+ .desc(`A destroyed device should not be able to create any valid bind groups.`)
+ .params(u =>
+ u
+ .combine('resourceType', kBindableResources)
+ .combine('entry', allBindingEntries(false))
+ .filter(({ resourceType, entry }) => {
+ const info = bindingTypeInfo(entry);
+ switch (info.resource) {
+ // Either type of sampler may be bound to a filtering sampler binding.
+ case 'filtSamp':
+ return resourceType === 'filtSamp' || resourceType === 'nonFiltSamp';
+ // But only non-filtering samplers can be used with non-filtering sampler bindings.
+ case 'nonFiltSamp':
+ return resourceType === 'nonFiltSamp';
+ default:
+ return info.resource === resourceType;
+ }
+ })
+ .beginSubcases()
+ .combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, resourceType, entry } = t.params;
+ const visibility = bindingTypeInfo(entry).validStages;
+ const layout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility, ...entry }],
+ });
+ const resource = t.getBindingResource(resourceType);
+ await t.executeAfterDestroy(() => {
+ t.device.createBindGroup({ layout, entries: [{ binding: 0, resource }] });
+ }, awaitLost);
+ });
+
+g.test('createPipelineLayout')
+ .desc(
+ `
+Tests creating pipeline layouts on destroyed device. Tests valid combinations of:
+ - Various bind groups with valid binding entries
+ - Maximum set of visibility for each binding entry
+ `
+ )
+ .params(u =>
+ u.combine('entry', allBindingEntries(false)).beginSubcases().combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, entry } = t.params;
+ const visibility = bindingTypeInfo(entry).validStages;
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility, ...entry }],
+ });
+ await t.executeAfterDestroy(() => {
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout],
+ });
+ }, awaitLost);
+ });
+
+g.test('createShaderModule')
+ .desc(
+ `
+Tests creating shader modules on destroyed device.
+ - Tests all shader stages: vertex, fragment, compute
+ `
+ )
+ .params(u =>
+ u.combine('stage', kShaderStageKeys).beginSubcases().combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, stage } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createShaderModule({ code: t.getNoOpShaderCode(stage) });
+ }, awaitLost);
+ });
+
+g.test('createComputePipeline')
+ .desc(
+ `
+Tests creating compute pipeline on destroyed device.
+ - Tests with a valid no-op compute shader
+ `
+ )
+ .params(u => u.beginSubcases().combine('awaitLost', [true, false]))
+ .fn(async t => {
+ const { awaitLost } = t.params;
+ const cShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('COMPUTE') });
+ await t.executeAfterDestroy(() => {
+ t.device.createComputePipeline({
+ layout: 'auto',
+ compute: { module: cShader, entryPoint: 'main' },
+ });
+ }, awaitLost);
+ });
+
+g.test('createRenderPipeline')
+ .desc(
+ `
+Tests creating render pipeline on destroyed device.
+ - Tests with valid no-op vertex and fragment shaders
+ `
+ )
+ .params(u => u.beginSubcases().combine('awaitLost', [true, false]))
+ .fn(async t => {
+ const { awaitLost } = t.params;
+ const vShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('VERTEX') });
+ const fShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('FRAGMENT') });
+ await t.executeAfterDestroy(() => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module: vShader, entryPoint: 'main' },
+ fragment: {
+ module: fShader,
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ });
+ }, awaitLost);
+ });
+
+g.test('createCommandEncoder')
+ .desc(
+ `
+Tests creating command encoders on destroyed device.
+ `
+ )
+ .params(u => u.beginSubcases().combine('awaitLost', [true, false]))
+ .fn(async t => {
+ const { awaitLost } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createCommandEncoder();
+ }, awaitLost);
+ });
+
+g.test('createRenderBundleEncoder')
+ .desc(
+ `
+Tests creating render bundle encoders on destroyed device.
+ - Tests various renderable texture color formats
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kRenderableColorTextureFormats)
+ .beginSubcases()
+ .combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { awaitLost, format } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createRenderBundleEncoder({ colorFormats: [format] });
+ }, awaitLost);
+ });
+
+g.test('createQuerySet')
+ .desc(
+ `
+Tests creating query sets on destroyed device.
+ - Tests various query set types
+ `
+ )
+ .params(u => u.combine('type', kQueryTypes).beginSubcases().combine('awaitLost', [true, false]))
+ .beforeAllSubcases(t => {
+ const { type } = t.params;
+ t.selectDeviceForQueryTypeOrSkipTestCase(type);
+ })
+ .fn(async t => {
+ const { awaitLost, type } = t.params;
+ await t.executeAfterDestroy(() => {
+ t.device.createQuerySet({ type, count: 4 });
+ }, awaitLost);
+ });
+
+g.test('command,copyBufferToBuffer')
+ .desc(
+ `
+Tests copyBufferToBuffer command with various uncompressed formats on destroyed device.
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const kBufferSize = 16;
+ const src = t.device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const dst = t.device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.copyBufferToBuffer(src, 0, dst, 0, kBufferSize);
+ return maker;
+ });
+ });
+
+g.test('command,copyBufferToTexture')
+ .desc(
+ `
+Tests copyBufferToTexture command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const format = 'rgba32uint';
+ const { bytesPerBlock, blockWidth, blockHeight } = kTextureFormatInfo[format];
+ const src = {
+ buffer: t.device.createBuffer({
+ size: bytesPerBlock,
+ usage: GPUBufferUsage.COPY_SRC,
+ }),
+ };
+ const dst = {
+ texture: t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUTextureUsage.COPY_DST,
+ format,
+ }),
+ };
+ const copySize = { width: blockWidth, height: blockHeight };
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.copyBufferToTexture(src, dst, copySize);
+ return maker;
+ });
+ });
+
+g.test('command,copyTextureToBuffer')
+ .desc(
+ `
+Tests copyTextureToBuffer command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const format = 'rgba32uint';
+ const { bytesPerBlock, blockWidth, blockHeight } = kTextureFormatInfo[format];
+ const src = {
+ texture: t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUTextureUsage.COPY_SRC,
+ format,
+ }),
+ };
+ const dst = {
+ buffer: t.device.createBuffer({
+ size: bytesPerBlock,
+ usage: GPUBufferUsage.COPY_DST,
+ }),
+ };
+ const copySize = { width: blockWidth, height: blockHeight };
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.copyTextureToBuffer(src, dst, copySize);
+ return maker;
+ });
+ });
+
+g.test('command,copyTextureToTexture')
+ .desc(
+ `
+Tests copyTextureToTexture command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const format = 'rgba32uint';
+ const { blockWidth, blockHeight } = kTextureFormatInfo[format];
+ const src = {
+ texture: t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUTextureUsage.COPY_SRC,
+ format,
+ }),
+ };
+ const dst = {
+ texture: t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUBufferUsage.COPY_DST,
+ format,
+ }),
+ };
+ const copySize = { width: blockWidth, height: blockHeight };
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.copyTextureToTexture(src, dst, copySize);
+ return maker;
+ });
+ });
+
+g.test('command,clearBuffer')
+ .desc(
+ `
+Tests encoding and finishing a clearBuffer command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const kBufferSize = 16;
+ const buffer = t.device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.clearBuffer(buffer, 0, kBufferSize);
+ return maker;
+ });
+ });
+
+g.test('command,writeTimestamp')
+ .desc(
+ `
+Tests encoding and finishing a writeTimestamp command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u
+ .combine('type', kQueryTypes)
+ .beginSubcases()
+ .combine('stage', kCommandValidationStages)
+ .combine('awaitLost', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { type } = t.params;
+
+ // writeTimestamp is only available for devices that enable the 'timestamp-query' feature.
+ const queryTypes = ['timestamp'];
+ if (type !== 'timestamp') {
+ queryTypes.push(type);
+ }
+
+ t.selectDeviceForQueryTypeOrSkipTestCase(queryTypes);
+ })
+ .fn(async t => {
+ const { type, stage, awaitLost } = t.params;
+ const querySet = t.device.createQuerySet({ type, count: 2 });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.writeTimestamp(querySet, 0);
+ return maker;
+ });
+ });
+
+g.test('command,resolveQuerySet')
+ .desc(
+ `
+Tests encoding and finishing a resolveQuerySet command on destroyed device.
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const kQueryCount = 2;
+ const querySet = t.createQuerySetWithState('valid');
+ const destination = t.createBufferWithState('valid', {
+ size: kQueryCount * 8,
+ usage: GPUBufferUsage.QUERY_RESOLVE,
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'non-pass', maker => {
+ maker.encoder.resolveQuerySet(querySet, 0, 1, destination, 0);
+ return maker;
+ });
+ });
+
+g.test('command,computePass,dispatch')
+ .desc(
+ `
+Tests encoding and dispatching a simple valid compute pass on destroyed device.
+ - Binds valid pipeline and bindgroups, then dispatches
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const cShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('COMPUTE') });
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: { module: cShader, entryPoint: 'main' },
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'compute pass', maker => {
+ maker.encoder.setPipeline(pipeline);
+ maker.encoder.dispatchWorkgroups(1);
+ return maker;
+ });
+ });
+
+g.test('command,renderPass,draw')
+ .desc(
+ `
+Tests encoding and finishing a simple valid render pass on destroyed device.
+ - Binds valid pipeline and bindgroups, then draws
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const vShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('VERTEX') });
+ const fShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('FRAGMENT') });
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module: vShader, entryPoint: 'main' },
+ fragment: {
+ module: fShader,
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'render pass', maker => {
+ maker.encoder.setPipeline(pipeline);
+ maker.encoder.draw(0);
+ return maker;
+ });
+ });
+
+g.test('command,renderPass,renderBundle')
+ .desc(
+ `
+Tests encoding and drawing a render pass including a render bundle on destroyed device.
+ - Binds valid pipeline and bindgroups, executes render bundle, then draws
+ - Tests finishing encoding on destroyed device
+ - Tests submitting command on destroyed device
+ `
+ )
+ .params(u =>
+ u.beginSubcases().combine('stage', kCommandValidationStages).combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { stage, awaitLost } = t.params;
+ const vShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('VERTEX') });
+ const fShader = t.device.createShaderModule({ code: t.getNoOpShaderCode('FRAGMENT') });
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: { module: vShader, entryPoint: 'main' },
+ fragment: {
+ module: fShader,
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ });
+ await t.executeCommandsAfterDestroy(stage, awaitLost, 'render bundle', maker => {
+ maker.encoder.setPipeline(pipeline);
+ maker.encoder.draw(0);
+ return maker;
+ });
+ });
+
+g.test('queue,writeBuffer')
+ .desc(
+ `
+Tests writeBuffer on queue on destroyed device.
+ `
+ )
+ .params(u =>
+ u.combine('numElements', [4, 8, 16]).beginSubcases().combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { numElements, awaitLost } = t.params;
+ const buffer = t.device.createBuffer({
+ size: numElements,
+ usage: GPUBufferUsage.COPY_DST,
+ });
+ const data = new Uint8Array(numElements);
+ await t.executeAfterDestroy(() => {
+ t.device.queue.writeBuffer(buffer, 0, data);
+ }, awaitLost);
+ });
+
+g.test('queue,writeTexture,2d,uncompressed_format')
+ .desc(
+ `
+Tests writeTexture on queue on destroyed device with uncompressed formats.
+ `
+ )
+ .params(u =>
+ u.combine('format', kRegularTextureFormats).beginSubcases().combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { format, awaitLost } = t.params;
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ const data = new Uint8Array(bytesPerBlock);
+ const texture = t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUTextureUsage.COPY_DST,
+ format,
+ });
+ await t.executeAfterDestroy(() => {
+ t.device.queue.writeTexture(
+ { texture },
+ data,
+ {},
+ { width: blockWidth, height: blockHeight }
+ );
+ }, awaitLost);
+ });
+
+g.test('queue,writeTexture,2d,compressed_format')
+ .desc(
+ `
+Tests writeTexture on queue on destroyed device with compressed formats.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kCompressedTextureFormats)
+ .beginSubcases()
+ .combine('awaitLost', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
+ })
+ .fn(async t => {
+ const { format, awaitLost } = t.params;
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ const data = new Uint8Array(bytesPerBlock);
+ const texture = t.device.createTexture({
+ size: { width: blockWidth, height: blockHeight },
+ usage: GPUTextureUsage.COPY_DST,
+ format,
+ });
+ await t.executeAfterDestroy(() => {
+ t.device.queue.writeTexture(
+ { texture },
+ data,
+ {},
+ { width: blockWidth, height: blockHeight }
+ );
+ }, awaitLost);
+ });
+
+g.test('queue,copyExternalImageToTexture,canvas')
+ .desc(
+ `
+Tests copyExternalImageToTexture from canvas on queue on destroyed device.
+ `
+ )
+ .params(u =>
+ u
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('contextType', kValidCanvasContextIds)
+ .filter(({ contextType }) => {
+ return canCopyFromCanvasContext(contextType);
+ })
+ .beginSubcases()
+ .combine('awaitLost', [true, false])
+ )
+ .fn(async t => {
+ const { canvasType, contextType, awaitLost } = t.params;
+ const canvas = createCanvas(t, canvasType, 1, 1);
+ const texture = t.device.createTexture({
+ size: { width: 1, height: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const ctx = canvas.getContext(contextType);
+ if (ctx === null) {
+ t.skip('Failed to get context for canvas element');
+ return;
+ }
+ t.tryTrackForCleanup(ctx);
+
+ await t.executeAfterDestroy(() => {
+ t.device.queue.copyExternalImageToTexture(
+ { source: canvas },
+ { texture },
+ { width: 1, height: 1 }
+ );
+ }, awaitLost);
+ });
+
+g.test('queue,copyExternalImageToTexture,imageBitmap')
+ .desc(
+ `
+Tests copyExternalImageToTexture from canvas on queue on destroyed device.
+ `
+ )
+ .params(u => u.beginSubcases().combine('awaitLost', [true, false]))
+ .fn(async t => {
+ const { awaitLost } = t.params;
+ if (typeof createImageBitmap === 'undefined') {
+ t.skip('Creating ImageBitmaps is not supported.');
+ }
+ const imageBitmap = await createImageBitmap(new ImageData(new Uint8ClampedArray(4), 1, 1));
+
+ const texture = t.device.createTexture({
+ size: { width: 1, height: 1 },
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ await t.executeAfterDestroy(() => {
+ t.device.queue.copyExternalImageToTexture(
+ { source: imageBitmap },
+ { texture },
+ { width: 1, height: 1 }
+ );
+ }, awaitLost);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/destroy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/destroy.spec.js
new file mode 100644
index 0000000000..8f21dc3269
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/destroy.spec.js
@@ -0,0 +1,117 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Destroying a texture more than once is allowed.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { kTextureAspects, kTextureFormatInfo } from '../../../capability_info.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('base')
+ .desc(`Test that it is valid to destroy a texture.`)
+ .fn(t => {
+ const texture = t.getSampledTexture();
+ texture.destroy();
+ });
+
+g.test('twice')
+ .desc(`Test that it is valid to destroy a destroyed texture.`)
+ .fn(t => {
+ const texture = t.getSampledTexture();
+ texture.destroy();
+ texture.destroy();
+ });
+
+g.test('submit_a_destroyed_texture_as_attachment')
+ .desc(
+ `
+Test that it is invalid to submit with a texture as {color, depth, stencil, depth-stencil} attachment
+that was destroyed {before, after} encoding finishes.
+`
+ )
+ .params(u =>
+ u //
+ .combine('depthStencilTextureAspect', kTextureAspects)
+ .combine('colorTextureState', ['valid', 'destroyedBeforeEncode', 'destroyedAfterEncode'])
+ .combine('depthStencilTextureState', [
+ 'valid',
+ 'destroyedBeforeEncode',
+ 'destroyedAfterEncode',
+ ])
+ )
+ .fn(async t => {
+ const { colorTextureState, depthStencilTextureAspect, depthStencilTextureState } = t.params;
+
+ const isSubmitSuccess = colorTextureState === 'valid' && depthStencilTextureState === 'valid';
+
+ const colorTextureFormat = 'rgba32float';
+ const depthStencilTextureFormat =
+ depthStencilTextureAspect === 'all'
+ ? 'depth24plus-stencil8'
+ : depthStencilTextureAspect === 'depth-only'
+ ? 'depth32float'
+ : 'stencil8';
+
+ const colorTextureDesc = {
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: colorTextureFormat,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ };
+
+ const depthStencilTextureDesc = {
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: depthStencilTextureFormat,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ };
+
+ const colorTexture = t.device.createTexture(colorTextureDesc);
+ const depthStencilTexture = t.device.createTexture(depthStencilTextureDesc);
+
+ if (colorTextureState === 'destroyedBeforeEncode') {
+ colorTexture.destroy();
+ }
+ if (depthStencilTextureState === 'destroyedBeforeEncode') {
+ depthStencilTexture.destroy();
+ }
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const depthStencilAttachment = {
+ view: depthStencilTexture.createView({ aspect: depthStencilTextureAspect }),
+ };
+ if (kTextureFormatInfo[depthStencilTextureFormat].depth) {
+ depthStencilAttachment.depthClearValue = 0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'discard';
+ }
+ if (kTextureFormatInfo[depthStencilTextureFormat].stencil) {
+ depthStencilAttachment.stencilClearValue = 0;
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'discard';
+ }
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorTexture.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+
+ depthStencilAttachment,
+ });
+ renderPass.end();
+
+ const cmd = commandEncoder.finish();
+
+ if (colorTextureState === 'destroyedAfterEncode') {
+ colorTexture.destroy();
+ }
+ if (depthStencilTextureState === 'destroyedAfterEncode') {
+ depthStencilTexture.destroy();
+ }
+
+ t.expectValidationError(() => t.queue.submit([cmd]), !isSubmitSuccess);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/rg11b10ufloat_renderable.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/rg11b10ufloat_renderable.spec.js
new file mode 100644
index 0000000000..1c48a376c0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/texture/rg11b10ufloat_renderable.spec.js
@@ -0,0 +1,109 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for capabilities added by rg11b10ufloat-renderable flag.
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUConst } from '../../../constants.js';
+import { ValidationTest } from '../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+g.test('create_texture')
+ .desc(
+ `
+Test that it is valid to create rg11b10ufloat texture with RENDER_ATTACHMENT usage and/or
+sampleCount > 1, iff rg11b10ufloat-renderable feature is enabled.
+Note, the createTexture tests cover these validation cases where this feature is not enabled.
+`
+ )
+ .params(u => u.combine('sampleCount', [1, 4]))
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase('rg11b10ufloat-renderable');
+ })
+ .fn(async t => {
+ const { sampleCount } = t.params;
+ const descriptor = {
+ size: [1, 1, 1],
+ format: 'rg11b10ufloat',
+ sampleCount,
+ usage: GPUConst.TextureUsage.RENDER_ATTACHMENT,
+ };
+ t.device.createTexture(descriptor);
+ });
+
+g.test('begin_render_pass')
+ .desc(
+ `
+Test that it is valid to begin render pass with rg11b10ufloat texture format
+iff rg11b10ufloat-renderable feature is enabled.
+`
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase('rg11b10ufloat-renderable');
+ })
+ .fn(async t => {
+ const texture = t.device.createTexture({
+ size: [1, 1, 1],
+ format: 'rg11b10ufloat',
+ sampleCount: 1,
+ usage: GPUConst.TextureUsage.RENDER_ATTACHMENT,
+ });
+ const encoder = t.device.createCommandEncoder();
+ encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: texture.createView(),
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ });
+
+g.test('begin_render_bundle_encoder')
+ .desc(
+ `
+Test that it is valid to begin render bundle encoder with rg11b10ufloat texture
+format iff rg11b10ufloat-renderable feature is enabled.
+`
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase('rg11b10ufloat-renderable');
+ })
+ .fn(async t => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: ['rg11b10ufloat'],
+ });
+ });
+
+g.test('create_render_pipeline')
+ .desc(
+ `
+Test that it is valid to create render pipeline with rg11b10ufloat texture format
+in descriptor.fragment.targets iff rg11b10ufloat-renderable feature is enabled.
+`
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase('rg11b10ufloat-renderable');
+ })
+ .fn(async t => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: t.getNoOpShaderCode('VERTEX'),
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: t.getNoOpShaderCode('FRAGMENT'),
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rg11b10ufloat', writeMask: 0 }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js
new file mode 100644
index 0000000000..bab6027f1a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/api/validation/validation_test.js
@@ -0,0 +1,422 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { kMaxQueryCount } from '../../capability_info.js';
+import { GPUTest } from '../../gpu_test.js';
+
+/**
+ * Base fixture for WebGPU validation tests.
+ */
+export class ValidationTest extends GPUTest {
+ /**
+ * Create a GPUTexture in the specified state.
+ * A `descriptor` may optionally be passed, which is used when `state` is not `'invalid'`.
+ */
+ createTextureWithState(state, descriptor) {
+ descriptor = descriptor ?? {
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage:
+ GPUTextureUsage.COPY_SRC |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.STORAGE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT,
+ };
+
+ switch (state) {
+ case 'valid':
+ return this.trackForCleanup(this.device.createTexture(descriptor));
+ case 'invalid':
+ return this.getErrorTexture();
+ case 'destroyed': {
+ const texture = this.device.createTexture(descriptor);
+ texture.destroy();
+ return texture;
+ }
+ }
+ }
+
+ /**
+ * Create a GPUTexture in the specified state. A `descriptor` may optionally be passed;
+ * if `state` is `'invalid'`, it will be modified to add an invalid combination of usages.
+ */
+ createBufferWithState(state, descriptor) {
+ descriptor = descriptor ?? {
+ size: 4,
+ usage: GPUBufferUsage.VERTEX,
+ };
+
+ switch (state) {
+ case 'valid':
+ return this.trackForCleanup(this.device.createBuffer(descriptor));
+
+ case 'invalid': {
+ // Make the buffer invalid because of an invalid combination of usages but keep the
+ // descriptor passed as much as possible (for mappedAtCreation and friends).
+ this.device.pushErrorScope('validation');
+ const buffer = this.device.createBuffer({
+ ...descriptor,
+ usage: descriptor.usage | GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_SRC,
+ });
+ void this.device.popErrorScope();
+ return buffer;
+ }
+ case 'destroyed': {
+ const buffer = this.device.createBuffer(descriptor);
+ buffer.destroy();
+ return buffer;
+ }
+ }
+ }
+
+ /**
+ * Create a GPUQuerySet in the specified state.
+ * A `descriptor` may optionally be passed, which is used when `state` is not `'invalid'`.
+ */
+ createQuerySetWithState(state, desc) {
+ const descriptor = { type: 'occlusion', count: 2, ...desc };
+
+ switch (state) {
+ case 'valid':
+ return this.trackForCleanup(this.device.createQuerySet(descriptor));
+ case 'invalid': {
+ // Make the queryset invalid because of the count out of bounds.
+ descriptor.count = kMaxQueryCount + 1;
+ return this.expectGPUError('validation', () => this.device.createQuerySet(descriptor));
+ }
+ case 'destroyed': {
+ const queryset = this.device.createQuerySet(descriptor);
+ queryset.destroy();
+ return queryset;
+ }
+ }
+ }
+
+ /** Create an arbitrarily-sized GPUBuffer with the STORAGE usage. */
+ getStorageBuffer() {
+ return this.trackForCleanup(
+ this.device.createBuffer({ size: 1024, usage: GPUBufferUsage.STORAGE })
+ );
+ }
+
+ /** Create an arbitrarily-sized GPUBuffer with the UNIFORM usage. */
+ getUniformBuffer() {
+ return this.trackForCleanup(
+ this.device.createBuffer({ size: 1024, usage: GPUBufferUsage.UNIFORM })
+ );
+ }
+
+ /** Return an invalid GPUBuffer. */
+ getErrorBuffer() {
+ return this.createBufferWithState('invalid');
+ }
+
+ /** Return an invalid GPUSampler. */
+ getErrorSampler() {
+ this.device.pushErrorScope('validation');
+ const sampler = this.device.createSampler({ lodMinClamp: -1 });
+ void this.device.popErrorScope();
+ return sampler;
+ }
+
+ /**
+ * Return an arbitrarily-configured GPUTexture with the `TEXTURE_BINDING` usage and specified
+ * sampleCount. The `RENDER_ATTACHMENT` usage will also be specified if sampleCount > 1 as is
+ * required by WebGPU SPEC.
+ */
+ getSampledTexture(sampleCount = 1) {
+ const usage =
+ sampleCount > 1
+ ? GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT
+ : GPUTextureUsage.TEXTURE_BINDING;
+ return this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage,
+ sampleCount,
+ })
+ );
+ }
+
+ /** Return an arbitrarily-configured GPUTexture with the `STORAGE_BINDING` usage. */
+ getStorageTexture() {
+ return this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.STORAGE_BINDING,
+ })
+ );
+ }
+
+ /** Return an arbitrarily-configured GPUTexture with the `RENDER_ATTACHMENT` usage. */
+ getRenderTexture(sampleCount = 1) {
+ return this.trackForCleanup(
+ this.device.createTexture({
+ size: { width: 16, height: 16, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount,
+ })
+ );
+ }
+
+ /** Return an invalid GPUTexture. */
+ getErrorTexture() {
+ this.device.pushErrorScope('validation');
+ const texture = this.device.createTexture({
+ size: { width: 0, height: 0, depthOrArrayLayers: 0 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ void this.device.popErrorScope();
+ return texture;
+ }
+
+ /** Return an invalid GPUTextureView (created from an invalid GPUTexture). */
+ getErrorTextureView() {
+ this.device.pushErrorScope('validation');
+ const view = this.getErrorTexture().createView();
+ void this.device.popErrorScope();
+ return view;
+ }
+
+ /**
+ * Return an arbitrary object of the specified {@link webgpu/capability_info!BindableResource} type
+ * (e.g. `'errorBuf'`, `'nonFiltSamp'`, `sampledTexMS`, etc.)
+ */
+ getBindingResource(bindingType) {
+ switch (bindingType) {
+ case 'errorBuf':
+ return { buffer: this.getErrorBuffer() };
+ case 'errorSamp':
+ return this.getErrorSampler();
+ case 'errorTex':
+ return this.getErrorTextureView();
+ case 'uniformBuf':
+ return { buffer: this.getUniformBuffer() };
+ case 'storageBuf':
+ return { buffer: this.getStorageBuffer() };
+ case 'filtSamp':
+ return this.device.createSampler({ minFilter: 'linear' });
+ case 'nonFiltSamp':
+ return this.device.createSampler();
+ case 'compareSamp':
+ return this.device.createSampler({ compare: 'never' });
+ case 'sampledTex':
+ return this.getSampledTexture(1).createView();
+ case 'sampledTexMS':
+ return this.getSampledTexture(4).createView();
+ case 'storageTex':
+ return this.getStorageTexture().createView();
+ }
+ }
+
+ /** Create an arbitrarily-sized GPUBuffer with the STORAGE usage from mismatched device. */
+ getDeviceMismatchedStorageBuffer() {
+ return this.trackForCleanup(
+ this.mismatchedDevice.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE })
+ );
+ }
+
+ /** Create an arbitrarily-sized GPUBuffer with the UNIFORM usage from mismatched device. */
+ getDeviceMismatchedUniformBuffer() {
+ return this.trackForCleanup(
+ this.mismatchedDevice.createBuffer({ size: 4, usage: GPUBufferUsage.UNIFORM })
+ );
+ }
+
+ /** Return a GPUTexture with descriptor from mismatched device. */
+ getDeviceMismatchedTexture(descriptor) {
+ return this.trackForCleanup(this.mismatchedDevice.createTexture(descriptor));
+ }
+
+ /** Return an arbitrarily-configured GPUTexture with the `SAMPLED` usage from mismatched device. */
+ getDeviceMismatchedSampledTexture(sampleCount = 1) {
+ return this.getDeviceMismatchedTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ sampleCount,
+ });
+ }
+
+ /** Return an arbitrarily-configured GPUTexture with the `STORAGE` usage from mismatched device. */
+ getDeviceMismatchedStorageTexture() {
+ return this.getDeviceMismatchedTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.STORAGE_BINDING,
+ });
+ }
+
+ /** Return an arbitrarily-configured GPUTexture with the `RENDER_ATTACHMENT` usage from mismatched device. */
+ getDeviceMismatchedRenderTexture(sampleCount = 1) {
+ return this.getDeviceMismatchedTexture({
+ size: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount,
+ });
+ }
+
+ getDeviceMismatchedBindingResource(bindingType) {
+ switch (bindingType) {
+ case 'uniformBuf':
+ return { buffer: this.getDeviceMismatchedStorageBuffer() };
+ case 'storageBuf':
+ return { buffer: this.getDeviceMismatchedUniformBuffer() };
+ case 'filtSamp':
+ return this.mismatchedDevice.createSampler({ minFilter: 'linear' });
+ case 'nonFiltSamp':
+ return this.mismatchedDevice.createSampler();
+ case 'compareSamp':
+ return this.mismatchedDevice.createSampler({ compare: 'never' });
+ case 'sampledTex':
+ return this.getDeviceMismatchedSampledTexture(1).createView();
+ case 'sampledTexMS':
+ return this.getDeviceMismatchedSampledTexture(4).createView();
+ case 'storageTex':
+ return this.getDeviceMismatchedStorageTexture().createView();
+ }
+ }
+
+ /** Return a no-op shader code snippet for the specified shader stage. */
+ getNoOpShaderCode(stage) {
+ switch (stage) {
+ case 'VERTEX':
+ return `
+ @vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+ }
+ `;
+ case 'FRAGMENT':
+ return `@fragment fn main() {}`;
+ case 'COMPUTE':
+ return `@compute @workgroup_size(1) fn main() {}`;
+ }
+ }
+
+ /** Create a GPURenderPipeline in the specified state. */
+ createRenderPipelineWithState(state) {
+ return state === 'valid' ? this.createNoOpRenderPipeline() : this.createErrorRenderPipeline();
+ }
+
+ /** Return a GPURenderPipeline with default options and no-op vertex and fragment shaders. */
+ createNoOpRenderPipeline(layout = 'auto') {
+ return this.device.createRenderPipeline({
+ layout,
+ vertex: {
+ module: this.device.createShaderModule({
+ code: this.getNoOpShaderCode('VERTEX'),
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: this.getNoOpShaderCode('FRAGMENT'),
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm', writeMask: 0 }],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+ }
+
+ /** Return an invalid GPURenderPipeline. */
+ createErrorRenderPipeline() {
+ this.device.pushErrorScope('validation');
+ const pipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: '',
+ }),
+ entryPoint: '',
+ },
+ });
+ void this.device.popErrorScope();
+ return pipeline;
+ }
+
+ /** Return a GPUComputePipeline with a no-op shader. */
+ createNoOpComputePipeline(layout = 'auto') {
+ return this.device.createComputePipeline({
+ layout,
+ compute: {
+ module: this.device.createShaderModule({
+ code: this.getNoOpShaderCode('COMPUTE'),
+ }),
+ entryPoint: 'main',
+ },
+ });
+ }
+
+ /** Return an invalid GPUComputePipeline. */
+ createErrorComputePipeline() {
+ this.device.pushErrorScope('validation');
+ const pipeline = this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({
+ code: '',
+ }),
+ entryPoint: '',
+ },
+ });
+ void this.device.popErrorScope();
+ return pipeline;
+ }
+
+ /** Return an invalid GPUShaderModule. */
+ createInvalidShaderModule() {
+ this.device.pushErrorScope('validation');
+ const code = 'deadbeaf'; // Something make no sense
+ const shaderModule = this.device.createShaderModule({ code });
+ void this.device.popErrorScope();
+ return shaderModule;
+ }
+
+ /** Helper for testing createRenderPipeline(Async) validation */
+ doCreateRenderPipelineTest(isAsync, _success, descriptor, errorTypeName = 'OperationError') {
+ if (isAsync) {
+ if (_success) {
+ this.shouldResolve(this.device.createRenderPipelineAsync(descriptor));
+ } else {
+ this.shouldReject(errorTypeName, this.device.createRenderPipelineAsync(descriptor));
+ }
+ } else {
+ if (errorTypeName === 'OperationError') {
+ this.expectValidationError(() => {
+ this.device.createRenderPipeline(descriptor);
+ }, !_success);
+ } else {
+ this.shouldThrow(_success ? false : errorTypeName, () => {
+ this.device.createRenderPipeline(descriptor);
+ });
+ }
+ }
+ }
+
+ /** Helper for testing createComputePipeline(Async) validation */
+ doCreateComputePipelineTest(isAsync, _success, descriptor, errorTypeName = 'OperationError') {
+ if (isAsync) {
+ if (_success) {
+ this.shouldResolve(this.device.createComputePipelineAsync(descriptor));
+ } else {
+ this.shouldReject(errorTypeName, this.device.createComputePipelineAsync(descriptor));
+ }
+ } else {
+ if (errorTypeName === 'OperationError') {
+ this.expectValidationError(() => {
+ this.device.createComputePipeline(descriptor);
+ }, !_success);
+ } else {
+ this.shouldThrow(_success ? false : errorTypeName, () => {
+ this.device.createComputePipeline(descriptor);
+ });
+ }
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js
new file mode 100644
index 0000000000..7c8e10cb7b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/capability_info.js
@@ -0,0 +1,1808 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // MAINTENANCE_TODO: The generated Typedoc for this file is hard to navigate because it's
+// alphabetized. Consider using namespaces or renames to fix this?
+
+import { keysOf, makeTable, numericKeysOf } from '../common/util/data_tables.js';
+import { assertTypeTrue } from '../common/util/types.js';
+import { assert, unreachable } from '../common/util/util.js';
+
+import { GPUConst, kMaxUnsignedLongValue, kMaxUnsignedLongLongValue } from './constants.js';
+
+// Base device limits can be found in constants.ts.
+
+// Queries
+
+/** Maximum number of queries in GPUQuerySet, by spec. */
+export const kMaxQueryCount = 4096;
+/** Per-GPUQueryType info. */
+
+export const kQueryTypeInfo = {
+ // Occlusion query does not require any features.
+ occlusion: { feature: undefined },
+ timestamp: { feature: 'timestamp-query' },
+};
+/** List of all GPUQueryType values. */
+export const kQueryTypes = keysOf(kQueryTypeInfo);
+
+// Buffers
+
+/** Required alignment of a GPUBuffer size, by spec. */
+export const kBufferSizeAlignment = 4;
+
+/** Per-GPUBufferUsage copy info. */
+export const kBufferUsageCopyInfo = {
+ COPY_NONE: 0,
+ COPY_SRC: GPUConst.BufferUsage.COPY_SRC,
+ COPY_DST: GPUConst.BufferUsage.COPY_DST,
+ COPY_SRC_DST: GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.COPY_DST,
+};
+/** List of all GPUBufferUsage copy values. */
+export const kBufferUsageCopy = keysOf(kBufferUsageCopyInfo);
+
+/** Per-GPUBufferUsage keys and info. */
+
+export const kBufferUsageKeys = keysOf(GPUConst.BufferUsage);
+export const kBufferUsageInfo = {
+ ...GPUConst.BufferUsage,
+};
+
+/** List of all GPUBufferUsage values. */
+export const kBufferUsages = Object.values(GPUConst.BufferUsage);
+export const kAllBufferUsageBits = kBufferUsages.reduce(
+ (previousSet, currentUsage) => previousSet | currentUsage,
+ 0
+);
+
+// Errors
+
+/** Per-GPUErrorFilter info. */
+export const kErrorScopeFilterInfo = {
+ 'out-of-memory': {},
+ validation: {},
+ internal: {},
+};
+/** List of all GPUErrorFilter values. */
+export const kErrorScopeFilters = keysOf(kErrorScopeFilterInfo);
+export const kGeneratableErrorScopeFilters = kErrorScopeFilters.filter(e => e !== 'internal');
+
+// Textures
+
+// Definitions for use locally. To access the table entries, use `kTextureFormatInfo`.
+
+// Note that we repeat the header multiple times in order to make it easier to read.
+const kRegularTextureFormatInfo = makeTable(
+ [
+ 'renderable',
+ 'multisample',
+ 'resolve',
+ 'color',
+ 'depth',
+ 'stencil',
+ 'storage',
+ 'copySrc',
+ 'copyDst',
+ 'sampleType',
+ 'bytesPerBlock',
+ 'blockWidth',
+ 'blockHeight',
+ 'renderTargetPixelByteCost',
+ 'renderTargetComponentAlignment',
+ 'feature',
+ 'baseFormat',
+ ],
+ [, , , true, false, false, , true, true, , , 1, 1, undefined, undefined, , undefined],
+ {
+ // 8-bit formats
+ r8unorm: [true, true, true, , , , false, , , 'float', 1, , , 1, 1],
+ r8snorm: [false, false, false, , , , false, , , 'float', 1],
+ r8uint: [true, true, false, , , , false, , , 'uint', 1, , , 1, 1],
+ r8sint: [true, true, false, , , , false, , , 'sint', 1, , , 1, 1],
+ // 16-bit formats
+ r16uint: [true, true, false, , , , false, , , 'uint', 2, , , 2, 2],
+ r16sint: [true, true, false, , , , false, , , 'sint', 2, , , 2, 2],
+ r16float: [true, true, true, , , , false, , , 'float', 2, , , 2, 2],
+ rg8unorm: [true, true, true, , , , false, , , 'float', 2, , , 2, 1],
+ rg8snorm: [false, false, false, , , , false, , , 'float', 2],
+ rg8uint: [true, true, false, , , , false, , , 'uint', 2, , , 2, 1],
+ rg8sint: [true, true, false, , , , false, , , 'sint', 2, , , 2, 1],
+ // 32-bit formats
+ r32uint: [true, false, false, , , , true, , , 'uint', 4, , , 4, 4],
+ r32sint: [true, false, false, , , , true, , , 'sint', 4, , , 4, 4],
+ r32float: [true, true, false, , , , true, , , 'unfilterable-float', 4, , , 4, 4],
+ rg16uint: [true, true, false, , , , false, , , 'uint', 4, , , 4, 2],
+ rg16sint: [true, true, false, , , , false, , , 'sint', 4, , , 4, 2],
+ rg16float: [true, true, true, , , , false, , , 'float', 4, , , 4, 2],
+ rgba8unorm: [true, true, true, , , , true, , , 'float', 4, , , 8, 1, , 'rgba8unorm'],
+ 'rgba8unorm-srgb': [true, true, true, , , , false, , , 'float', 4, , , 8, 1, , 'rgba8unorm'],
+ rgba8snorm: [false, false, false, , , , true, , , 'float', 4],
+ rgba8uint: [true, true, false, , , , true, , , 'uint', 4, , , 4, 1],
+ rgba8sint: [true, true, false, , , , true, , , 'sint', 4, , , 4, 1],
+ bgra8unorm: [true, true, true, , , , false, , , 'float', 4, , , 8, 1, , 'bgra8unorm'],
+ 'bgra8unorm-srgb': [true, true, true, , , , false, , , 'float', 4, , , 8, 1, , 'bgra8unorm'],
+ // Packed 32-bit formats
+ rgb10a2unorm: [true, true, true, , , , false, , , 'float', 4, , , 8, 4],
+ rg11b10ufloat: [false, false, false, , , , false, , , 'float', 4, , , 8, 4],
+ rgb9e5ufloat: [false, false, false, , , , false, , , 'float', 4],
+ // 64-bit formats
+ rg32uint: [true, false, false, , , , true, , , 'uint', 8, , , 8, 4],
+ rg32sint: [true, false, false, , , , true, , , 'sint', 8, , , 8, 4],
+ rg32float: [true, false, false, , , , true, , , 'unfilterable-float', 8, , , 8, 4],
+ rgba16uint: [true, true, false, , , , true, , , 'uint', 8, , , 8, 2],
+ rgba16sint: [true, true, false, , , , true, , , 'sint', 8, , , 8, 2],
+ rgba16float: [true, true, true, , , , true, , , 'float', 8, , , 8, 2],
+ // 128-bit formats
+ rgba32uint: [true, false, false, , , , true, , , 'uint', 16, , , 16, 4],
+ rgba32sint: [true, false, false, , , , true, , , 'sint', 16, , , 16, 4],
+ rgba32float: [true, false, false, , , , true, , , 'unfilterable-float', 16, , , 16, 4],
+ }
+);
+
+const kTexFmtInfoHeader = [
+ 'renderable',
+ 'multisample',
+ 'resolve',
+ 'color',
+ 'depth',
+ 'stencil',
+ 'storage',
+ 'copySrc',
+ 'copyDst',
+ 'sampleType',
+ 'bytesPerBlock',
+ 'blockWidth',
+ 'blockHeight',
+ 'renderTargetPixelByteCost',
+ 'renderTargetComponentAlignment',
+ 'feature',
+ 'baseFormat',
+];
+const kSizedDepthStencilFormatInfo = makeTable(
+ kTexFmtInfoHeader,
+ [true, true, false, false, , , false, , , , , 1, 1, undefined, undefined, , undefined],
+ {
+ depth32float: [, , , , true, false, , true, false, 'depth', 4],
+ depth16unorm: [, , , , true, false, , true, true, 'depth', 2],
+ stencil8: [, , , , false, true, , true, true, 'uint', 1],
+ }
+);
+
+// Multi aspect sample type are now set to their first aspect
+const kUnsizedDepthStencilFormatInfo = makeTable(
+ kTexFmtInfoHeader,
+ [true, true, false, false, , , false, false, false, , undefined, 1, 1, , , , undefined],
+ {
+ depth24plus: [, , , , true, false, , , , 'depth'],
+ 'depth24plus-stencil8': [, , , , true, true, , , , 'depth'],
+ // MAINTENANCE_TODO: These should really be sized formats; see below MAINTENANCE_TODO about multi-aspect formats.
+ 'depth32float-stencil8': [, , , , true, true, , , , 'depth', , , , , , 'depth32float-stencil8'],
+ }
+);
+
+// Separated compressed formats by type
+const kBCTextureFormatInfo = makeTable(
+ kTexFmtInfoHeader,
+ [false, false, false, true, false, false, false, true, true, , , 4, 4, , , , undefined],
+ {
+ // Block Compression (BC) formats
+ 'bc1-rgba-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc1-rgba-unorm',
+ ],
+ 'bc1-rgba-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc1-rgba-unorm',
+ ],
+ 'bc2-rgba-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc2-rgba-unorm',
+ ],
+ 'bc2-rgba-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc2-rgba-unorm',
+ ],
+ 'bc3-rgba-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc3-rgba-unorm',
+ ],
+ 'bc3-rgba-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc3-rgba-unorm',
+ ],
+ 'bc4-r-unorm': [, , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc'],
+ 'bc4-r-snorm': [, , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-bc'],
+ 'bc5-rg-unorm': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
+ 'bc5-rg-snorm': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
+ 'bc6h-rgb-ufloat': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
+ 'bc6h-rgb-float': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-bc'],
+ 'bc7-rgba-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc7-rgba-unorm',
+ ],
+ 'bc7-rgba-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-bc',
+ 'bc7-rgba-unorm',
+ ],
+ }
+);
+const kETC2TextureFormatInfo = makeTable(
+ kTexFmtInfoHeader,
+ [false, false, false, true, false, false, false, true, true, , , 4, 4, , , , undefined],
+ {
+ // Ericsson Compression (ETC2) formats
+ 'etc2-rgb8unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgb8unorm',
+ ],
+ 'etc2-rgb8unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgb8unorm',
+ ],
+ 'etc2-rgb8a1unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgb8a1unorm',
+ ],
+ 'etc2-rgb8a1unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 8,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgb8a1unorm',
+ ],
+ 'etc2-rgba8unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgba8unorm',
+ ],
+ 'etc2-rgba8unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-etc2',
+ 'etc2-rgba8unorm',
+ ],
+ 'eac-r11unorm': [, , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2'],
+ 'eac-r11snorm': [, , , , , , , , , 'float', 8, 4, 4, , , 'texture-compression-etc2'],
+ 'eac-rg11unorm': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2'],
+ 'eac-rg11snorm': [, , , , , , , , , 'float', 16, 4, 4, , , 'texture-compression-etc2'],
+ }
+);
+const kASTCTextureFormatInfo = makeTable(
+ kTexFmtInfoHeader,
+ [false, false, false, true, false, false, false, true, true, , , , , , , , undefined],
+ {
+ // Adaptable Scalable Compression (ASTC) formats
+ 'astc-4x4-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-4x4-unorm',
+ ],
+ 'astc-4x4-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 4,
+ 4,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-4x4-unorm',
+ ],
+ 'astc-5x4-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 5,
+ 4,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-5x4-unorm',
+ ],
+ 'astc-5x4-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 5,
+ 4,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-5x4-unorm',
+ ],
+ 'astc-5x5-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 5,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-5x5-unorm',
+ ],
+ 'astc-5x5-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 5,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-5x5-unorm',
+ ],
+ 'astc-6x5-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 6,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-6x5-unorm',
+ ],
+ 'astc-6x5-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 6,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-6x5-unorm',
+ ],
+ 'astc-6x6-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 6,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-6x6-unorm',
+ ],
+ 'astc-6x6-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 6,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-6x6-unorm',
+ ],
+ 'astc-8x5-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x5-unorm',
+ ],
+ 'astc-8x5-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x5-unorm',
+ ],
+ 'astc-8x6-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x6-unorm',
+ ],
+ 'astc-8x6-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x6-unorm',
+ ],
+ 'astc-8x8-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 8,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x8-unorm',
+ ],
+ 'astc-8x8-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 8,
+ 8,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-8x8-unorm',
+ ],
+ 'astc-10x5-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x5-unorm',
+ ],
+ 'astc-10x5-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 5,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x5-unorm',
+ ],
+ 'astc-10x6-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x6-unorm',
+ ],
+ 'astc-10x6-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 6,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x6-unorm',
+ ],
+ 'astc-10x8-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 8,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x8-unorm',
+ ],
+ 'astc-10x8-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 8,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x8-unorm',
+ ],
+ 'astc-10x10-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 10,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x10-unorm',
+ ],
+ 'astc-10x10-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 10,
+ 10,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-10x10-unorm',
+ ],
+ 'astc-12x10-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 12,
+ 10,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-12x10-unorm',
+ ],
+ 'astc-12x10-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 12,
+ 10,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-12x10-unorm',
+ ],
+ 'astc-12x12-unorm': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 12,
+ 12,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-12x12-unorm',
+ ],
+ 'astc-12x12-unorm-srgb': [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+ 'float',
+ 16,
+ 12,
+ 12,
+ ,
+ ,
+ 'texture-compression-astc',
+ 'astc-12x12-unorm',
+ ],
+ }
+);
+
+// Definitions for use locally. To access the table entries, use `kTextureFormatInfo`.
+
+// MAINTENANCE_TODO: Consider generating the exports below programmatically by filtering the big list, instead
+// of using these local constants? Requires some type magic though.
+const kCompressedTextureFormatInfo = {
+ ...kBCTextureFormatInfo,
+ ...kETC2TextureFormatInfo,
+ ...kASTCTextureFormatInfo,
+};
+const kColorTextureFormatInfo = { ...kRegularTextureFormatInfo, ...kCompressedTextureFormatInfo };
+const kEncodableTextureFormatInfo = {
+ ...kRegularTextureFormatInfo,
+ ...kSizedDepthStencilFormatInfo,
+};
+const kSizedTextureFormatInfo = {
+ ...kRegularTextureFormatInfo,
+ ...kSizedDepthStencilFormatInfo,
+ ...kCompressedTextureFormatInfo,
+};
+const kDepthStencilFormatInfo = {
+ ...kSizedDepthStencilFormatInfo,
+ ...kUnsizedDepthStencilFormatInfo,
+};
+const kUncompressedTextureFormatInfo = {
+ ...kRegularTextureFormatInfo,
+ ...kSizedDepthStencilFormatInfo,
+ ...kUnsizedDepthStencilFormatInfo,
+};
+const kAllTextureFormatInfo = {
+ ...kUncompressedTextureFormatInfo,
+ ...kCompressedTextureFormatInfo,
+};
+
+/** A "regular" texture format (uncompressed, sized, single-plane color formats). */
+
+export const kRegularTextureFormats = keysOf(kRegularTextureFormatInfo);
+export const kSizedDepthStencilFormats = keysOf(kSizedDepthStencilFormatInfo);
+export const kUnsizedDepthStencilFormats = keysOf(kUnsizedDepthStencilFormatInfo);
+export const kCompressedTextureFormats = keysOf(kCompressedTextureFormatInfo);
+
+export const kColorTextureFormats = keysOf(kColorTextureFormatInfo);
+export const kEncodableTextureFormats = keysOf(kEncodableTextureFormatInfo);
+export const kSizedTextureFormats = keysOf(kSizedTextureFormatInfo);
+export const kDepthStencilFormats = keysOf(kDepthStencilFormatInfo);
+export const kUncompressedTextureFormats = keysOf(kUncompressedTextureFormatInfo);
+export const kAllTextureFormats = keysOf(kAllTextureFormatInfo);
+
+// CompressedTextureFormat are unrenderable so filter from RegularTextureFormats for color targets is enough
+export const kRenderableColorTextureFormats = kRegularTextureFormats.filter(
+ v => kColorTextureFormatInfo[v].renderable
+);
+
+assert(
+ kRenderableColorTextureFormats.every(
+ f =>
+ kAllTextureFormatInfo[f].renderTargetComponentAlignment !== undefined &&
+ kAllTextureFormatInfo[f].renderTargetPixelByteCost !== undefined
+ )
+);
+
+// The formats of GPUTextureFormat for canvas context.
+export const kCanvasTextureFormats = ['bgra8unorm', 'rgba8unorm', 'rgba16float'];
+
+// The alpha mode for canvas context.
+export const kCanvasAlphaModesInfo = {
+ opaque: {},
+ premultiplied: {},
+};
+export const kCanvasAlphaModes = keysOf(kCanvasAlphaModesInfo);
+
+// The color spaces for canvas context
+export const kCanvasColorSpacesInfo = {
+ srgb: {},
+ 'display-p3': {},
+};
+export const kCanvasColorSpaces = keysOf(kCanvasColorSpacesInfo);
+
+/** Per-GPUTextureFormat info. */
+// Exists just for documentation. Otherwise could be inferred by `makeTable`.
+// MAINTENANCE_TODO: Refactor this to separate per-aspect data for multi-aspect formats. In particular:
+// - bytesPerBlock only makes sense on a per-aspect basis. But this table can't express that.
+// So we put depth32float-stencil8 to be an unsized format for now.
+
+/** Per-GPUTextureFormat info. */
+export const kTextureFormatInfo = kAllTextureFormatInfo;
+/** List of all GPUTextureFormat values. */
+export const kTextureFormats = keysOf(kAllTextureFormatInfo);
+
+/** Valid GPUTextureFormats for `copyExternalImageToTexture`, by spec. */
+export const kValidTextureFormatsForCopyE2T = [
+ 'r8unorm',
+ 'r16float',
+ 'r32float',
+ 'rg8unorm',
+ 'rg16float',
+ 'rg32float',
+ 'rgba8unorm',
+ 'rgba8unorm-srgb',
+ 'bgra8unorm',
+ 'bgra8unorm-srgb',
+ 'rgb10a2unorm',
+ 'rgba16float',
+ 'rgba32float',
+];
+
+/** Per-GPUTextureDimension info. */
+export const kTextureDimensionInfo = {
+ '1d': {},
+ '2d': {},
+ '3d': {},
+};
+/** List of all GPUTextureDimension values. */
+export const kTextureDimensions = keysOf(kTextureDimensionInfo);
+
+/** Per-GPUTextureAspect info. */
+export const kTextureAspectInfo = {
+ all: {},
+ 'depth-only': {},
+ 'stencil-only': {},
+};
+/** List of all GPUTextureAspect values. */
+export const kTextureAspects = keysOf(kTextureAspectInfo);
+
+/** Per-GPUCompareFunction info. */
+export const kCompareFunctionInfo = {
+ never: {},
+ less: {},
+ equal: {},
+ 'less-equal': {},
+ greater: {},
+ 'not-equal': {},
+ 'greater-equal': {},
+ always: {},
+};
+/** List of all GPUCompareFunction values. */
+export const kCompareFunctions = keysOf(kCompareFunctionInfo);
+
+/** Per-GPUStencilOperation info. */
+export const kStencilOperationInfo = {
+ keep: {},
+ zero: {},
+ replace: {},
+ invert: {},
+ 'increment-clamp': {},
+ 'decrement-clamp': {},
+ 'increment-wrap': {},
+ 'decrement-wrap': {},
+};
+/** List of all GPUStencilOperation values. */
+export const kStencilOperations = keysOf(kStencilOperationInfo);
+
+const kDepthStencilFormatCapabilityInBufferTextureCopy = {
+ // kUnsizedDepthStencilFormats
+ depth24plus: {
+ CopyB2T: [],
+ CopyT2B: [],
+ texelAspectSize: { 'depth-only': -1, 'stencil-only': -1 },
+ },
+ 'depth24plus-stencil8': {
+ CopyB2T: ['stencil-only'],
+ CopyT2B: ['stencil-only'],
+ texelAspectSize: { 'depth-only': -1, 'stencil-only': 1 },
+ },
+
+ // kSizedDepthStencilFormats
+ depth16unorm: {
+ CopyB2T: ['all', 'depth-only'],
+ CopyT2B: ['all', 'depth-only'],
+ texelAspectSize: { 'depth-only': 2, 'stencil-only': -1 },
+ },
+ depth32float: {
+ CopyB2T: [],
+ CopyT2B: ['all', 'depth-only'],
+ texelAspectSize: { 'depth-only': 4, 'stencil-only': -1 },
+ },
+ 'depth32float-stencil8': {
+ CopyB2T: ['stencil-only'],
+ CopyT2B: ['depth-only', 'stencil-only'],
+ texelAspectSize: { 'depth-only': 4, 'stencil-only': 1 },
+ },
+ stencil8: {
+ CopyB2T: ['all', 'stencil-only'],
+ CopyT2B: ['all', 'stencil-only'],
+ texelAspectSize: { 'depth-only': -1, 'stencil-only': 1 },
+ },
+};
+
+/** `kDepthStencilFormatResolvedAspect[format][aspect]` returns the aspect-specific format for a
+ * depth-stencil format, or `undefined` if the format doesn't have the aspect.
+ */
+export const kDepthStencilFormatResolvedAspect = {
+ // kUnsizedDepthStencilFormats
+ depth24plus: {
+ all: 'depth24plus',
+ 'depth-only': 'depth24plus',
+ 'stencil-only': undefined,
+ },
+ 'depth24plus-stencil8': {
+ all: 'depth24plus-stencil8',
+ 'depth-only': 'depth24plus',
+ 'stencil-only': 'stencil8',
+ },
+
+ // kSizedDepthStencilFormats
+ depth16unorm: {
+ all: 'depth16unorm',
+ 'depth-only': 'depth16unorm',
+ 'stencil-only': undefined,
+ },
+ depth32float: {
+ all: 'depth32float',
+ 'depth-only': 'depth32float',
+ 'stencil-only': undefined,
+ },
+ 'depth32float-stencil8': {
+ all: 'depth32float-stencil8',
+ 'depth-only': 'depth32float',
+ 'stencil-only': 'stencil8',
+ },
+ stencil8: {
+ all: 'stencil8',
+ 'depth-only': undefined,
+ 'stencil-only': 'stencil8',
+ },
+};
+
+/**
+ * @returns the GPUTextureFormat corresponding to the @param aspect of @param format.
+ * This allows choosing the correct format for depth-stencil aspects when creating pipelines that
+ * will have to match the resolved format of views, or to get per-aspect information like the
+ * `blockByteSize`.
+ *
+ * Many helpers use an `undefined` `aspect` to means `'all'` so this is also the default for this
+ * function.
+ */
+export function resolvePerAspectFormat(format, aspect) {
+ if (aspect === 'all' || aspect === undefined) {
+ return format;
+ }
+ assert(kTextureFormatInfo[format].depth || kTextureFormatInfo[format].stencil);
+ const resolved = kDepthStencilFormatResolvedAspect[format][aspect ?? 'all'];
+ assert(resolved !== undefined);
+ return resolved;
+}
+
+/**
+ * Gets all copyable aspects for copies between texture and buffer for specified depth/stencil format and copy type, by spec.
+ */
+export function depthStencilFormatCopyableAspects(type, format) {
+ const appliedType = type === 'WriteTexture' ? 'CopyB2T' : type;
+ return kDepthStencilFormatCapabilityInBufferTextureCopy[format][appliedType];
+}
+
+/**
+ * Computes whether a copy between a depth/stencil texture aspect and a buffer is supported, by spec.
+ */
+export function depthStencilBufferTextureCopySupported(type, format, aspect) {
+ const supportedAspects = depthStencilFormatCopyableAspects(type, format);
+
+ return supportedAspects.includes(aspect);
+}
+
+/**
+ * Returns the byte size of the depth or stencil aspect of the specified depth/stencil format,
+ * or -1 if none.
+ */
+export function depthStencilFormatAspectSize(format, aspect) {
+ const texelAspectSize =
+ kDepthStencilFormatCapabilityInBufferTextureCopy[format].texelAspectSize[aspect];
+ assert(texelAspectSize > 0);
+ return texelAspectSize;
+}
+
+/**
+ * Returns true iff a texture can be created with the provided GPUTextureDimension
+ * (defaulting to 2d) and GPUTextureFormat, by spec.
+ */
+export function textureDimensionAndFormatCompatible(dimension, format) {
+ const info = kAllTextureFormatInfo[format];
+ return !(
+ (dimension === '1d' || dimension === '3d') &&
+ (info.blockWidth > 1 || info.depth || info.stencil)
+ );
+}
+
+/** Per-GPUTextureUsage type info. */
+export const kTextureUsageTypeInfo = {
+ texture: Number(GPUConst.TextureUsage.TEXTURE_BINDING),
+ storage: Number(GPUConst.TextureUsage.STORAGE_BINDING),
+ render: Number(GPUConst.TextureUsage.RENDER_ATTACHMENT),
+};
+/** List of all GPUTextureUsage type values. */
+export const kTextureUsageType = keysOf(kTextureUsageTypeInfo);
+
+/** Per-GPUTextureUsage copy info. */
+export const kTextureUsageCopyInfo = {
+ none: 0,
+ src: Number(GPUConst.TextureUsage.COPY_SRC),
+ dst: Number(GPUConst.TextureUsage.COPY_DST),
+ 'src-dest': Number(GPUConst.TextureUsage.COPY_SRC) | Number(GPUConst.TextureUsage.COPY_DST),
+};
+/** List of all GPUTextureUsage copy values. */
+export const kTextureUsageCopy = keysOf(kTextureUsageCopyInfo);
+
+/** Per-GPUTextureUsage info. */
+export const kTextureUsageInfo = {
+ [GPUConst.TextureUsage.COPY_SRC]: {},
+ [GPUConst.TextureUsage.COPY_DST]: {},
+ [GPUConst.TextureUsage.TEXTURE_BINDING]: {},
+ [GPUConst.TextureUsage.STORAGE_BINDING]: {},
+ [GPUConst.TextureUsage.RENDER_ATTACHMENT]: {},
+};
+/** List of all GPUTextureUsage values. */
+export const kTextureUsages = numericKeysOf(kTextureUsageInfo);
+
+// Texture View
+
+/** Per-GPUTextureViewDimension info. */
+
+/** Per-GPUTextureViewDimension info. */
+export const kTextureViewDimensionInfo = {
+ '1d': { storage: true },
+ '2d': { storage: true },
+ '2d-array': { storage: true },
+ cube: { storage: false },
+ 'cube-array': { storage: false },
+ '3d': { storage: true },
+};
+/** List of all GPUTextureDimension values. */
+export const kTextureViewDimensions = keysOf(kTextureViewDimensionInfo);
+
+// Vertex formats
+
+/** Per-GPUVertexFormat info. */
+// Exists just for documentation. Otherwise could be inferred by `makeTable`.
+
+/** Per-GPUVertexFormat info. */
+export const kVertexFormatInfo = makeTable(
+ ['bytesPerComponent', 'type', 'componentCount', 'wgslType'],
+ [, , ,],
+ {
+ // 8 bit components
+ uint8x2: [1, 'uint', 2, 'vec2<u32>'],
+ uint8x4: [1, 'uint', 4, 'vec4<u32>'],
+ sint8x2: [1, 'sint', 2, 'vec2<i32>'],
+ sint8x4: [1, 'sint', 4, 'vec4<i32>'],
+ unorm8x2: [1, 'unorm', 2, 'vec2<f32>'],
+ unorm8x4: [1, 'unorm', 4, 'vec4<f32>'],
+ snorm8x2: [1, 'snorm', 2, 'vec2<f32>'],
+ snorm8x4: [1, 'snorm', 4, 'vec4<f32>'],
+ // 16 bit components
+ uint16x2: [2, 'uint', 2, 'vec2<u32>'],
+ uint16x4: [2, 'uint', 4, 'vec4<u32>'],
+ sint16x2: [2, 'sint', 2, 'vec2<i32>'],
+ sint16x4: [2, 'sint', 4, 'vec4<i32>'],
+ unorm16x2: [2, 'unorm', 2, 'vec2<f32>'],
+ unorm16x4: [2, 'unorm', 4, 'vec4<f32>'],
+ snorm16x2: [2, 'snorm', 2, 'vec2<f32>'],
+ snorm16x4: [2, 'snorm', 4, 'vec4<f32>'],
+ float16x2: [2, 'float', 2, 'vec2<f32>'],
+ float16x4: [2, 'float', 4, 'vec4<f32>'],
+ // 32 bit components
+ float32: [4, 'float', 1, 'f32'],
+ float32x2: [4, 'float', 2, 'vec2<f32>'],
+ float32x3: [4, 'float', 3, 'vec3<f32>'],
+ float32x4: [4, 'float', 4, 'vec4<f32>'],
+ uint32: [4, 'uint', 1, 'u32'],
+ uint32x2: [4, 'uint', 2, 'vec2<u32>'],
+ uint32x3: [4, 'uint', 3, 'vec3<u32>'],
+ uint32x4: [4, 'uint', 4, 'vec4<u32>'],
+ sint32: [4, 'sint', 1, 'i32'],
+ sint32x2: [4, 'sint', 2, 'vec2<i32>'],
+ sint32x3: [4, 'sint', 3, 'vec3<i32>'],
+ sint32x4: [4, 'sint', 4, 'vec4<i32>'],
+ }
+);
+/** List of all GPUVertexFormat values. */
+export const kVertexFormats = keysOf(kVertexFormatInfo);
+
+// Typedefs for bindings
+
+/**
+ * Classes of `PerShaderStage` binding limits. Two bindings with the same class
+ * count toward the same `PerShaderStage` limit(s) in the spec (if any).
+ */
+
+export const kBindableResources = [
+ 'uniformBuf',
+ 'storageBuf',
+ 'filtSamp',
+ 'nonFiltSamp',
+ 'compareSamp',
+ 'sampledTex',
+ 'sampledTexMS',
+ 'storageTex',
+ 'errorBuf',
+ 'errorSamp',
+ 'errorTex',
+];
+
+assertTypeTrue();
+
+// Bindings
+
+/** Dynamic buffer offsets require offset to be divisible by 256, by spec. */
+export const kMinDynamicBufferOffsetAlignment = 256;
+
+/** Default `PerShaderStage` binding limits, by spec. */
+export const kPerStageBindingLimits = {
+ uniformBuf: { class: 'uniformBuf', max: 12 },
+ storageBuf: { class: 'storageBuf', max: 8 },
+ sampler: { class: 'sampler', max: 16 },
+ sampledTex: { class: 'sampledTex', max: 16 },
+ storageTex: { class: 'storageTex', max: 4 },
+};
+
+/**
+ * Default `PerPipelineLayout` binding limits, by spec.
+ */
+export const kPerPipelineBindingLimits = {
+ uniformBuf: { class: 'uniformBuf', maxDynamic: 8 },
+ storageBuf: { class: 'storageBuf', maxDynamic: 4 },
+ sampler: { class: 'sampler', maxDynamic: 0 },
+ sampledTex: { class: 'sampledTex', maxDynamic: 0 },
+ storageTex: { class: 'storageTex', maxDynamic: 0 },
+};
+
+const kBindingKind = {
+ uniformBuf: {
+ resource: 'uniformBuf',
+ perStageLimitClass: kPerStageBindingLimits.uniformBuf,
+ perPipelineLimitClass: kPerPipelineBindingLimits.uniformBuf,
+ },
+ storageBuf: {
+ resource: 'storageBuf',
+ perStageLimitClass: kPerStageBindingLimits.storageBuf,
+ perPipelineLimitClass: kPerPipelineBindingLimits.storageBuf,
+ },
+ filtSamp: {
+ resource: 'filtSamp',
+ perStageLimitClass: kPerStageBindingLimits.sampler,
+ perPipelineLimitClass: kPerPipelineBindingLimits.sampler,
+ },
+ nonFiltSamp: {
+ resource: 'nonFiltSamp',
+ perStageLimitClass: kPerStageBindingLimits.sampler,
+ perPipelineLimitClass: kPerPipelineBindingLimits.sampler,
+ },
+ compareSamp: {
+ resource: 'compareSamp',
+ perStageLimitClass: kPerStageBindingLimits.sampler,
+ perPipelineLimitClass: kPerPipelineBindingLimits.sampler,
+ },
+ sampledTex: {
+ resource: 'sampledTex',
+ perStageLimitClass: kPerStageBindingLimits.sampledTex,
+ perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex,
+ },
+ sampledTexMS: {
+ resource: 'sampledTexMS',
+ perStageLimitClass: kPerStageBindingLimits.sampledTex,
+ perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex,
+ },
+ storageTex: {
+ resource: 'storageTex',
+ perStageLimitClass: kPerStageBindingLimits.storageTex,
+ perPipelineLimitClass: kPerPipelineBindingLimits.storageTex,
+ },
+};
+
+// Binding type info
+
+const kValidStagesAll = {
+ validStages:
+ GPUConst.ShaderStage.VERTEX | GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
+};
+const kValidStagesStorageWrite = {
+ validStages: GPUConst.ShaderStage.FRAGMENT | GPUConst.ShaderStage.COMPUTE,
+};
+
+/** Binding type info (including class limits) for the specified GPUBufferBindingLayout. */
+export function bufferBindingTypeInfo(d) {
+ switch (d.type ?? 'uniform') {
+ case 'uniform':
+ return {
+ usage: GPUConst.BufferUsage.UNIFORM,
+ ...kBindingKind.uniformBuf,
+ ...kValidStagesAll,
+ };
+ case 'storage':
+ return {
+ usage: GPUConst.BufferUsage.STORAGE,
+ ...kBindingKind.storageBuf,
+ ...kValidStagesStorageWrite,
+ };
+ case 'read-only-storage':
+ return {
+ usage: GPUConst.BufferUsage.STORAGE,
+ ...kBindingKind.storageBuf,
+ ...kValidStagesAll,
+ };
+ }
+}
+/** List of all GPUBufferBindingType values. */
+export const kBufferBindingTypes = ['uniform', 'storage', 'read-only-storage'];
+assertTypeTrue();
+
+/** Binding type info (including class limits) for the specified GPUSamplerBindingLayout. */
+export function samplerBindingTypeInfo(d) {
+ switch (d.type ?? 'filtering') {
+ case 'filtering':
+ return { ...kBindingKind.filtSamp, ...kValidStagesAll };
+ case 'non-filtering':
+ return { ...kBindingKind.nonFiltSamp, ...kValidStagesAll };
+ case 'comparison':
+ return { ...kBindingKind.compareSamp, ...kValidStagesAll };
+ }
+}
+/** List of all GPUSamplerBindingType values. */
+export const kSamplerBindingTypes = ['filtering', 'non-filtering', 'comparison'];
+assertTypeTrue();
+
+/** Binding type info (including class limits) for the specified GPUTextureBindingLayout. */
+export function sampledTextureBindingTypeInfo(d) {
+ if (d.multisampled) {
+ return {
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ ...kBindingKind.sampledTexMS,
+ ...kValidStagesAll,
+ };
+ } else {
+ return {
+ usage: GPUConst.TextureUsage.TEXTURE_BINDING,
+ ...kBindingKind.sampledTex,
+ ...kValidStagesAll,
+ };
+ }
+}
+/** List of all GPUTextureSampleType values. */
+export const kTextureSampleTypes = ['float', 'unfilterable-float', 'depth', 'sint', 'uint'];
+
+assertTypeTrue();
+
+/** Binding type info (including class limits) for the specified GPUStorageTextureBindingLayout. */
+export function storageTextureBindingTypeInfo(d) {
+ return {
+ usage: GPUConst.TextureUsage.STORAGE_BINDING,
+ ...kBindingKind.storageTex,
+ ...kValidStagesStorageWrite,
+ };
+}
+/** List of all GPUStorageTextureAccess values. */
+export const kStorageTextureAccessValues = ['write-only'];
+assertTypeTrue();
+
+/** GPUBindGroupLayoutEntry, but only the "union" fields, not the common fields. */
+
+/** Binding type info (including class limits) for the specified BGLEntry. */
+export function texBindingTypeInfo(e) {
+ if (e.texture !== undefined) return sampledTextureBindingTypeInfo(e.texture);
+ if (e.storageTexture !== undefined) return storageTextureBindingTypeInfo(e.storageTexture);
+ unreachable();
+}
+/** BindingTypeInfo (including class limits) for the specified BGLEntry. */
+export function bindingTypeInfo(e) {
+ if (e.buffer !== undefined) return bufferBindingTypeInfo(e.buffer);
+ if (e.texture !== undefined) return sampledTextureBindingTypeInfo(e.texture);
+ if (e.sampler !== undefined) return samplerBindingTypeInfo(e.sampler);
+ if (e.storageTexture !== undefined) return storageTextureBindingTypeInfo(e.storageTexture);
+ unreachable('GPUBindGroupLayoutEntry has no BindingLayout');
+}
+
+/**
+ * Generate a list of possible buffer-typed BGLEntry values.
+ *
+ * Note: Generates different `type` options, but not `hasDynamicOffset` options.
+ */
+export function bufferBindingEntries(includeUndefined) {
+ return [
+ ...(includeUndefined ? [{ buffer: { type: undefined } }] : []),
+ { buffer: { type: 'uniform' } },
+ { buffer: { type: 'storage' } },
+ { buffer: { type: 'read-only-storage' } },
+ ];
+}
+/** Generate a list of possible sampler-typed BGLEntry values. */
+export function samplerBindingEntries(includeUndefined) {
+ return [
+ ...(includeUndefined ? [{ sampler: { type: undefined } }] : []),
+ { sampler: { type: 'comparison' } },
+ { sampler: { type: 'filtering' } },
+ { sampler: { type: 'non-filtering' } },
+ ];
+}
+/**
+ * Generate a list of possible texture-typed BGLEntry values.
+ *
+ * Note: Generates different `multisampled` options, but not `sampleType` or `viewDimension` options.
+ */
+export function textureBindingEntries(includeUndefined) {
+ return [
+ ...(includeUndefined ? [{ texture: { multisampled: undefined } }] : []),
+ { texture: { multisampled: false } },
+ { texture: { multisampled: true } },
+ ];
+}
+/**
+ * Generate a list of possible storageTexture-typed BGLEntry values.
+ *
+ * Note: Generates different `access` options, but not `format` or `viewDimension` options.
+ */
+export function storageTextureBindingEntries(format) {
+ return [{ storageTexture: { access: 'write-only', format } }];
+}
+/** Generate a list of possible texture-or-storageTexture-typed BGLEntry values. */
+export function sampledAndStorageBindingEntries(
+ includeUndefined,
+ storageTextureFormat = 'rgba8unorm'
+) {
+ return [
+ ...textureBindingEntries(includeUndefined),
+ ...storageTextureBindingEntries(storageTextureFormat),
+ ];
+}
+/**
+ * Generate a list of possible BGLEntry values of every type, but not variants with different:
+ * - buffer.hasDynamicOffset
+ * - texture.sampleType
+ * - texture.viewDimension
+ * - storageTexture.viewDimension
+ */
+export function allBindingEntries(includeUndefined, storageTextureFormat = 'rgba8unorm') {
+ return [
+ ...bufferBindingEntries(includeUndefined),
+ ...samplerBindingEntries(includeUndefined),
+ ...sampledAndStorageBindingEntries(includeUndefined, storageTextureFormat),
+ ];
+}
+
+// Shader stages
+
+/** List of all GPUShaderStage values. */
+
+export const kShaderStageKeys = Object.keys(GPUConst.ShaderStage);
+export const kShaderStages = [
+ GPUConst.ShaderStage.VERTEX,
+ GPUConst.ShaderStage.FRAGMENT,
+ GPUConst.ShaderStage.COMPUTE,
+];
+
+/** List of all possible combinations of GPUShaderStage values. */
+export const kShaderStageCombinations = [0, 1, 2, 3, 4, 5, 6, 7];
+
+/**
+ * List of all possible texture sampleCount values.
+ *
+ * MAINTENANCE_TODO: Switch existing tests to use kTextureSampleCounts
+ */
+export const kTextureSampleCounts = [1, 4];
+
+// Blend factors and Blend components
+
+/** List of all GPUBlendFactor values. */
+export const kBlendFactors = [
+ 'zero',
+ 'one',
+ 'src',
+ 'one-minus-src',
+ 'src-alpha',
+ 'one-minus-src-alpha',
+ 'dst',
+ 'one-minus-dst',
+ 'dst-alpha',
+ 'one-minus-dst-alpha',
+ 'src-alpha-saturated',
+ 'constant',
+ 'one-minus-constant',
+];
+
+/** List of all GPUBlendOperation values. */
+export const kBlendOperations = [
+ 'add', //
+ 'subtract',
+ 'reverse-subtract',
+ 'min',
+ 'max',
+];
+
+// Primitive topologies
+export const kPrimitiveTopology = [
+ 'point-list',
+ 'line-list',
+ 'line-strip',
+ 'triangle-list',
+ 'triangle-strip',
+];
+
+assertTypeTrue();
+
+export const kIndexFormat = ['uint16', 'uint32'];
+assertTypeTrue();
+
+/** Info for each entry of GPUSupportedLimits */
+export const kLimitInfo = makeTable(
+ ['class', 'default', 'maximumValue'],
+ ['maximum', , kMaxUnsignedLongValue],
+ {
+ maxTextureDimension1D: [, 8192],
+ maxTextureDimension2D: [, 8192],
+ maxTextureDimension3D: [, 2048],
+ maxTextureArrayLayers: [, 256],
+
+ maxBindGroups: [, 4],
+ maxDynamicUniformBuffersPerPipelineLayout: [, 8],
+ maxDynamicStorageBuffersPerPipelineLayout: [, 4],
+ maxSampledTexturesPerShaderStage: [, 16],
+ maxSamplersPerShaderStage: [, 16],
+ maxStorageBuffersPerShaderStage: [, 8],
+ maxStorageTexturesPerShaderStage: [, 4],
+ maxUniformBuffersPerShaderStage: [, 12],
+
+ maxUniformBufferBindingSize: [, 65536, kMaxUnsignedLongLongValue],
+ maxStorageBufferBindingSize: [, 134217728, kMaxUnsignedLongLongValue],
+ minUniformBufferOffsetAlignment: ['alignment', 256],
+ minStorageBufferOffsetAlignment: ['alignment', 256],
+
+ maxVertexBuffers: [, 8],
+ maxBufferSize: [, 268435456, kMaxUnsignedLongLongValue],
+ maxVertexAttributes: [, 16],
+ maxVertexBufferArrayStride: [, 2048],
+ maxInterStageShaderComponents: [, 60],
+
+ maxColorAttachments: [, 8],
+ maxColorAttachmentBytesPerSample: [, 32],
+
+ maxComputeWorkgroupStorageSize: [, 16384],
+ maxComputeInvocationsPerWorkgroup: [, 256],
+ maxComputeWorkgroupSizeX: [, 256],
+ maxComputeWorkgroupSizeY: [, 256],
+ maxComputeWorkgroupSizeZ: [, 64],
+ maxComputeWorkgroupsPerDimension: [, 65535],
+ }
+);
+
+/** List of all entries of GPUSupportedLimits. */
+export const kLimits = keysOf(kLimitInfo);
+
+// Pipeline limits
+
+/** Maximum number of color attachments to a render pass, by spec. */
+export const kMaxColorAttachments = kLimitInfo.maxColorAttachments.default;
+/** `maxVertexBuffers` per GPURenderPipeline, by spec. */
+export const kMaxVertexBuffers = kLimitInfo.maxVertexBuffers.default;
+/** `maxVertexAttributes` per GPURenderPipeline, by spec. */
+export const kMaxVertexAttributes = kLimitInfo.maxVertexAttributes.default;
+/** `maxVertexBufferArrayStride` in a vertex buffer in a GPURenderPipeline, by spec. */
+export const kMaxVertexBufferArrayStride = kLimitInfo.maxVertexBufferArrayStride.default;
+
+/** The size of indirect draw parameters in the indirectBuffer of drawIndirect */
+export const kDrawIndirectParametersSize = 4;
+/** The size of indirect drawIndexed parameters in the indirectBuffer of drawIndexedIndirect */
+export const kDrawIndexedIndirectParametersSize = 5;
+
+/** Per-GPUFeatureName info. */
+export const kFeatureNameInfo = {
+ 'depth-clip-control': {},
+ 'depth32float-stencil8': {},
+ 'texture-compression-bc': {},
+ 'texture-compression-etc2': {},
+ 'texture-compression-astc': {},
+ 'timestamp-query': {},
+ 'indirect-first-instance': {},
+ 'shader-f16': {},
+ 'rg11b10ufloat-renderable': {},
+};
+/** List of all GPUFeatureName values. */
+export const kFeatureNames = keysOf(kFeatureNameInfo);
+
+/**
+ * Check if two formats are view format compatible.
+ *
+ * This function may need to be generalized to use `baseFormat` from `kTextureFormatInfo`.
+ */
+export function viewCompatible(a, b) {
+ return a === b || a + '-srgb' === b || b + '-srgb' === a;
+}
+
+export function getFeaturesForFormats(formats) {
+ return Array.from(new Set(formats.map(f => (f ? kTextureFormatInfo[f].feature : undefined))));
+}
+
+export function filterFormatsByFeature(feature, formats) {
+ return formats.filter(f => f === undefined || kTextureFormatInfo[f].feature === feature);
+}
+
+export const kFeaturesForFormats = getFeaturesForFormats(kTextureFormats);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js
new file mode 100644
index 0000000000..ff512c3f6b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/constants.js
@@ -0,0 +1,62 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // Note: Types ensure every field is specified.
+function checkType(x) {}
+
+const BufferUsage = {
+ MAP_READ: 0x0001,
+ MAP_WRITE: 0x0002,
+ COPY_SRC: 0x0004,
+ COPY_DST: 0x0008,
+ INDEX: 0x0010,
+ VERTEX: 0x0020,
+ UNIFORM: 0x0040,
+ STORAGE: 0x0080,
+ INDIRECT: 0x0100,
+ QUERY_RESOLVE: 0x0200,
+};
+checkType(BufferUsage);
+
+const TextureUsage = {
+ COPY_SRC: 0x01,
+ COPY_DST: 0x02,
+ TEXTURE_BINDING: 0x04,
+ SAMPLED: 0x04,
+ STORAGE_BINDING: 0x08,
+ STORAGE: 0x08,
+ RENDER_ATTACHMENT: 0x10,
+};
+checkType(TextureUsage);
+
+const ColorWrite = {
+ RED: 0x1,
+ GREEN: 0x2,
+ BLUE: 0x4,
+ ALPHA: 0x8,
+ ALL: 0xf,
+};
+checkType(ColorWrite);
+
+const ShaderStage = {
+ VERTEX: 0x1,
+ FRAGMENT: 0x2,
+ COMPUTE: 0x4,
+};
+checkType(ShaderStage);
+
+const MapMode = {
+ READ: 0x1,
+ WRITE: 0x2,
+};
+checkType(MapMode);
+
+export const GPUConst = {
+ BufferUsage,
+ TextureUsage,
+ ColorWrite,
+ ShaderStage,
+ MapMode,
+};
+
+export const kMaxUnsignedLongValue = 4294967295;
+export const kMaxUnsignedLongLongValue = Number.MAX_SAFE_INTEGER;
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/examples.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/examples.spec.js
new file mode 100644
index 0000000000..d99dfccea9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/examples.spec.js
@@ -0,0 +1,275 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Examples of writing CTS tests with various features.
+
+Start here when looking for examples of basic framework usage.
+`;
+import { makeTestGroup } from '../common/framework/test_group.js';
+
+import { GPUTest } from './gpu_test.js';
+
+// To run these tests in the standalone runner, run `npm start` then open:
+// - http://localhost:XXXX/standalone/?runnow=1&q=webgpu:examples:*
+// To run in WPT, copy/symlink the out-wpt/ directory as the webgpu/ directory in WPT, then open:
+// - (wpt server url)/webgpu/cts.https.html?q=webgpu:examples:
+//
+// Tests here can be run individually or in groups:
+// - ?q=webgpu:examples:basic,async:
+// - ?q=webgpu:examples:basic,async:*
+// - ?q=webgpu:examples:basic,*
+// - ?q=webgpu:examples:*
+
+export const g = makeTestGroup(GPUTest);
+
+// Note: spaces aren't allowed in test names; use underscores.
+g.test('test_name').fn(t => {});
+
+g.test('not_implemented_yet,without_plan').unimplemented();
+g.test('not_implemented_yet,with_plan')
+ .desc(
+ `
+Plan for this test. What it tests. Summary of how it tests that functionality.
+- Description of cases, by describing parameters {a, b, c}
+- x= more parameters {x, y, z}
+`
+ )
+ .unimplemented();
+
+g.test('basic').fn(t => {
+ t.expect(true);
+ t.expect(true, 'true should be true');
+
+ t.shouldThrow(
+ // The expected '.name' of the thrown error.
+ 'TypeError',
+ // This function is run inline inside shouldThrow, and is expected to throw.
+ () => {
+ throw new TypeError();
+ },
+ // Log message.
+ 'function should throw Error'
+ );
+});
+
+g.test('basic,async').fn(async t => {
+ // shouldReject must be awaited to ensure it can wait for the promise before the test ends.
+ t.shouldReject(
+ // The expected '.name' of the thrown error.
+ 'TypeError',
+ // Promise expected to reject.
+ Promise.reject(new TypeError()),
+ // Log message.
+ 'Promise.reject should reject'
+ );
+
+ // Promise can also be an IIFE.
+ t.shouldReject(
+ 'TypeError',
+ (async () => {
+ throw new TypeError();
+ })(),
+ 'Promise.reject should reject'
+ );
+});
+
+g.test('basic,plain_cases')
+ .desc(
+ `
+A test can be parameterized with a simple array of objects using .paramsSimple([ ... ]).
+Each such instance of the test is a "case".
+
+In this example, the following cases are generated (identified by their "query string"),
+each with just one subcase:
+ - webgpu:examples:basic,cases:x=2;y=2 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 2 }
+ - webgpu:examples:basic,cases:x=-10;y=-10 runs 1 subcase, with t.params set to:
+ - { x: -10, y: -10 }
+ `
+ )
+ .paramsSimple([
+ { x: 2, y: 2 }, //
+ { x: -10, y: -10 },
+ ])
+ .fn(t => {
+ t.expect(t.params.x === t.params.y);
+ });
+
+g.test('basic,plain_cases_private')
+ .desc(
+ `
+Parameters can be public ("x", "y") which means they're part of the case name.
+They can also be private by starting with an underscore ("_result"), which passes
+them into the test but does not make them part of the case name:
+
+In this example, the following cases are generated, each with just one subcase:
+ - webgpu:examples:basic,cases:x=2;y=4 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 4, _result: 6 }
+ - webgpu:examples:basic,cases:x=-10;y=18 runs 1 subcase, with t.params set to:
+ - { x: -10, y: 18, _result: 8 }
+ `
+ )
+ .paramsSimple([
+ { x: 2, y: 4, _result: 6 }, //
+ { x: -10, y: 18, _result: 8 },
+ ])
+ .fn(t => {
+ t.expect(t.params.x + t.params.y === t.params._result);
+ });
+// (note the blank comment above to enforce newlines on autoformat)
+
+g.test('basic,builder_cases')
+ .desc(
+ `
+A "CaseParamsBuilder" or "SubcaseParamsBuilder" can be passed to .params() instead.
+The params builder provides facilities for generating tests combinatorially (by cartesian
+product). For convenience, the "unit" CaseParamsBuilder is passed as an argument ("u" below).
+
+In this example, the following cases are generated, each with just one subcase:
+ - webgpu:examples:basic,cases:x=1,y=1 runs 1 subcase, with t.params set to:
+ - { x: 1, y: 1 }
+ - webgpu:examples:basic,cases:x=1,y=2 runs 1 subcase, with t.params set to:
+ - { x: 1, y: 2 }
+ - webgpu:examples:basic,cases:x=2,y=1 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 1 }
+ - webgpu:examples:basic,cases:x=2,y=2 runs 1 subcase, with t.params set to:
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_cases_subcases')
+ .desc(
+ `
+Each case sub-parameterized using .beginSubcases().
+Each such instance of the test is a "subcase", which cannot be run independently of other
+subcases. It is somewhat like wrapping the entire fn body in a for-loop.
+
+In this example, the following cases are generated:
+ - webgpu:examples:basic,cases:x=1 runs 2 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - webgpu:examples:basic,cases:x=2 runs 2 subcases, with t.params set to:
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .beginSubcases()
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_subcases')
+ .desc(
+ `
+In this example, the following single case is generated:
+ - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .params(u =>
+ u //
+ .beginSubcases()
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('basic,builder_subcases_short')
+ .desc(
+ `
+As a shorthand, .paramsSubcasesOnly() can be used.
+
+In this example, the following single case is generated:
+ - webgpu:examples:basic,cases: runs 4 subcases, with t.params set to:
+ - { x: 1, y: 1 }
+ - { x: 1, y: 2 }
+ - { x: 2, y: 1 }
+ - { x: 2, y: 2 }
+ `
+ )
+ .paramsSubcasesOnly(u =>
+ u //
+ .combineWithParams([{ x: 1 }, { x: 2 }])
+ .combineWithParams([{ y: 1 }, { y: 2 }])
+ )
+ .fn(() => {});
+
+g.test('gpu,async').fn(async t => {
+ const x = await t.queue.onSubmittedWorkDone();
+ t.expect(x === undefined);
+});
+
+g.test('gpu,buffers').fn(async t => {
+ const data = new Uint32Array([0, 1234, 0]);
+ const src = t.makeBufferWithContents(data, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
+
+ // Use the expectGPUBufferValuesEqual helper to check the actual contents of a GPUBuffer.
+ // This makes a copy and then asynchronously checks the contents. The test fixture will
+ // wait on that result before reporting whether the test passed or failed.
+ t.expectGPUBufferValuesEqual(src, data);
+});
+
+// One of the following two tests should be skipped on most platforms.
+
+g.test('gpu,with_texture_compression,bc')
+ .desc(
+ `Example of a test using a device descriptor.
+Tests that a BC format passes validation iff the feature is enabled.`
+ )
+ .params(u => u.combine('textureCompressionBC', [false, true]))
+ .beforeAllSubcases(t => {
+ const { textureCompressionBC } = t.params;
+
+ if (textureCompressionBC) {
+ t.selectDeviceOrSkipTestCase('texture-compression-bc');
+ }
+ })
+ .fn(async t => {
+ const { textureCompressionBC } = t.params;
+ const shouldError = !textureCompressionBC;
+ t.shouldThrow(shouldError ? 'TypeError' : false, () => {
+ t.device.createTexture({
+ format: 'bc1-rgba-unorm',
+ size: [4, 4, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });
+
+g.test('gpu,with_texture_compression,etc2')
+ .desc(
+ `Example of a test using a device descriptor.
+Tests that an ETC2 format passes validation iff the feature is enabled.`
+ )
+ .params(u => u.combine('textureCompressionETC2', [false, true]))
+ .beforeAllSubcases(t => {
+ const { textureCompressionETC2 } = t.params;
+
+ if (textureCompressionETC2) {
+ t.selectDeviceOrSkipTestCase('texture-compression-etc2');
+ }
+ })
+ .fn(async t => {
+ const { textureCompressionETC2 } = t.params;
+
+ const shouldError = !textureCompressionETC2;
+ t.shouldThrow(shouldError ? 'TypeError' : false, () => {
+ t.device.createTexture({
+ format: 'etc2-rgb8unorm',
+ size: [4, 4, 1],
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js
new file mode 100644
index 0000000000..caa7b7238a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/gpu_test.js
@@ -0,0 +1,941 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { Fixture, SubcaseBatchState } from '../common/framework/fixture.js';
+import { assert, range, unreachable } from '../common/util/util.js';
+
+import { kTextureFormatInfo, kQueryTypeInfo, resolvePerAspectFormat } from './capability_info.js';
+import { makeBufferWithContents } from './util/buffer.js';
+import {
+ checkElementsEqual,
+ checkElementsBetween,
+ checkElementsFloat16Between,
+} from './util/check_contents.js';
+import { CommandBufferMaker } from './util/command_buffer_maker.js';
+
+import { DevicePool } from './util/device_pool.js';
+import { align, roundDown } from './util/math.js';
+import { makeTextureWithContents } from './util/texture.js';
+import { getTextureCopyLayout, getTextureSubCopyLayout } from './util/texture/layout.js';
+import { kTexelRepresentationInfo } from './util/texture/texel_data.js';
+
+const devicePool = new DevicePool();
+
+// MAINTENANCE_TODO: When DevicePool becomes able to provide multiple devices at once, use the
+// usual one instead of a new one.
+const mismatchedDevicePool = new DevicePool();
+
+const kResourceStateValues = ['valid', 'invalid', 'destroyed'];
+
+export const kResourceStates = kResourceStateValues;
+
+/** Various "convenient" shorthands for GPUDeviceDescriptors for selectDevice functions. */
+
+export function initUncanonicalizedDeviceDescriptor(descriptor) {
+ if (typeof descriptor === 'string') {
+ return { requiredFeatures: [descriptor] };
+ } else if (descriptor instanceof Array) {
+ return {
+ requiredFeatures: descriptor.filter(f => f !== undefined),
+ };
+ } else {
+ return descriptor;
+ }
+}
+
+export class GPUTestSubcaseBatchState extends SubcaseBatchState {
+ /** Provider for default device. */
+
+ /** Provider for mismatched device. */
+
+ async postInit() {
+ // Skip all subcases if there's no device.
+ await this.acquireProvider();
+ }
+
+ async finalize() {
+ await super.finalize();
+
+ // Ensure devicePool.release is called for both providers even if one rejects.
+ await Promise.all([
+ this.provider?.then(x => devicePool.release(x)),
+ this.mismatchedProvider?.then(x => devicePool.release(x)),
+ ]);
+ }
+
+ /** @internal MAINTENANCE_TODO: Make this not visible to test code? */
+ acquireProvider() {
+ if (this.provider === undefined) {
+ this.selectDeviceOrSkipTestCase(undefined);
+ }
+ assert(this.provider !== undefined);
+ return this.provider;
+ }
+
+ /**
+ * Some tests or cases need particular feature flags or limits to be enabled.
+ * Call this function with a descriptor or feature name (or `undefined`) to select a
+ * GPUDevice with matching capabilities. If this isn't called, a default device is provided.
+ *
+ * If the request isn't supported, throws a SkipTestCase exception to skip the entire test case.
+ */
+ selectDeviceOrSkipTestCase(descriptor) {
+ assert(this.provider === undefined, "Can't selectDeviceOrSkipTestCase() multiple times");
+ this.provider = devicePool.acquire(initUncanonicalizedDeviceDescriptor(descriptor));
+ // Suppress uncaught promise rejection (we'll catch it later).
+ this.provider.catch(() => {});
+ }
+
+ /**
+ * Convenience function for {@link selectDeviceOrSkipTestCase}.
+ * Select a device with the features required by these texture format(s).
+ * If the device creation fails, then skip the test case.
+ */
+ selectDeviceForTextureFormatOrSkipTestCase(formats) {
+ if (!Array.isArray(formats)) {
+ formats = [formats];
+ }
+ const features = new Set();
+ for (const format of formats) {
+ if (format !== undefined) {
+ features.add(kTextureFormatInfo[format].feature);
+ }
+ }
+
+ this.selectDeviceOrSkipTestCase(Array.from(features));
+ }
+
+ /**
+ * Convenience function for {@link selectDeviceOrSkipTestCase}.
+ * Select a device with the features required by these query type(s).
+ * If the device creation fails, then skip the test case.
+ */
+ selectDeviceForQueryTypeOrSkipTestCase(types) {
+ if (!Array.isArray(types)) {
+ types = [types];
+ }
+ const features = types.map(t => kQueryTypeInfo[t].feature);
+ this.selectDeviceOrSkipTestCase(features);
+ }
+
+ /** @internal MAINTENANCE_TODO: Make this not visible to test code? */
+ acquireMismatchedProvider() {
+ return this.mismatchedProvider;
+ }
+
+ /**
+ * Some tests need a second device which is different from the first.
+ * This requests a second device so it will be available during the test. If it is not called,
+ * no second device will be available.
+ *
+ * If the request isn't supported, throws a SkipTestCase exception to skip the entire test case.
+ */
+ selectMismatchedDeviceOrSkipTestCase(descriptor) {
+ assert(
+ this.mismatchedProvider === undefined,
+ "Can't selectMismatchedDeviceOrSkipTestCase() multiple times"
+ );
+
+ this.mismatchedProvider = mismatchedDevicePool.acquire(
+ initUncanonicalizedDeviceDescriptor(descriptor)
+ );
+
+ // Suppress uncaught promise rejection (we'll catch it later).
+ this.mismatchedProvider.catch(() => {});
+ }
+}
+
+/**
+ * Base fixture for WebGPU tests.
+ */
+export class GPUTest extends Fixture {
+ static MakeSharedState(params) {
+ return new GPUTestSubcaseBatchState(params);
+ }
+
+ // Should never be undefined in a test. If it is, init() must not have run/finished.
+
+ async init() {
+ await super.init();
+
+ this.provider = await this.sharedState.acquireProvider();
+ this.mismatchedProvider = await this.sharedState.acquireMismatchedProvider();
+ }
+
+ /**
+ * GPUDevice for the test to use.
+ */
+ get device() {
+ assert(this.provider !== undefined, 'internal error: GPUDevice missing?');
+ return this.provider.device;
+ }
+
+ /**
+ * GPUDevice for tests requiring a second device different from the default one,
+ * e.g. for creating objects for by device_mismatch validation tests.
+ */
+ get mismatchedDevice() {
+ assert(
+ this.mismatchedProvider !== undefined,
+ 'selectMismatchedDeviceOrSkipTestCase was not called in beforeAllSubcases'
+ );
+
+ return this.mismatchedProvider.device;
+ }
+
+ /** GPUQueue for the test to use. (Same as `t.device.queue`.) */
+ get queue() {
+ return this.device.queue;
+ }
+
+ /** Snapshot a GPUBuffer's contents, returning a new GPUBuffer with the `MAP_READ` usage. */
+ createCopyForMapRead(src, srcOffset, size) {
+ assert(srcOffset % 4 === 0);
+ assert(size % 4 === 0);
+
+ const dst = this.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(dst);
+
+ const c = this.device.createCommandEncoder();
+ c.copyBufferToBuffer(src, srcOffset, dst, 0, size);
+ this.queue.submit([c.finish()]);
+
+ return dst;
+ }
+
+ /**
+ * Offset and size passed to createCopyForMapRead must be divisible by 4. For that
+ * we might need to copy more bytes from the buffer than we want to map.
+ * begin and end values represent the part of the copied buffer that stores the contents
+ * we initially wanted to map.
+ * The copy will not cause an OOB error because the buffer size must be 4-aligned.
+ */
+ createAlignedCopyForMapRead(src, size, offset) {
+ const alignedOffset = roundDown(offset, 4);
+ const subarrayByteStart = offset - alignedOffset;
+ const alignedSize = align(size + subarrayByteStart, 4);
+ const mappable = this.createCopyForMapRead(src, alignedOffset, alignedSize);
+ return { mappable, subarrayByteStart };
+ }
+
+ /**
+ * Snapshot the current contents of a range of a GPUBuffer, and return them as a TypedArray.
+ * Also provides a cleanup() function to unmap and destroy the staging buffer.
+ */
+ async readGPUBufferRangeTyped(src, { srcByteOffset = 0, method = 'copy', type, typedLength }) {
+ assert(
+ srcByteOffset % type.BYTES_PER_ELEMENT === 0,
+ 'srcByteOffset must be a multiple of BYTES_PER_ELEMENT'
+ );
+
+ const byteLength = typedLength * type.BYTES_PER_ELEMENT;
+ let mappable;
+ let mapOffset, mapSize, subarrayByteStart;
+ if (method === 'copy') {
+ ({ mappable, subarrayByteStart } = this.createAlignedCopyForMapRead(
+ src,
+ byteLength,
+ srcByteOffset
+ ));
+ } else if (method === 'map') {
+ mappable = src;
+ mapOffset = roundDown(srcByteOffset, 8);
+ mapSize = align(byteLength, 4);
+ subarrayByteStart = srcByteOffset - mapOffset;
+ } else {
+ unreachable();
+ }
+
+ assert(subarrayByteStart % type.BYTES_PER_ELEMENT === 0);
+ const subarrayStart = subarrayByteStart / type.BYTES_PER_ELEMENT;
+
+ // 2. Map the staging buffer, and create the TypedArray from it.
+ await mappable.mapAsync(GPUMapMode.READ, mapOffset, mapSize);
+ const mapped = new type(mappable.getMappedRange(mapOffset, mapSize));
+ const data = mapped.subarray(subarrayStart, typedLength);
+
+ return {
+ data,
+ cleanup() {
+ mappable.unmap();
+ mappable.destroy();
+ },
+ };
+ }
+
+ /**
+ * Expect a GPUBuffer's contents to pass the provided check.
+ *
+ * A library of checks can be found in {@link webgpu/util/check_contents}.
+ */
+ expectGPUBufferValuesPassCheck(
+ src,
+ check,
+ { srcByteOffset = 0, type, typedLength, method = 'copy', mode = 'fail' }
+ ) {
+ const readbackPromise = this.readGPUBufferRangeTyped(src, {
+ srcByteOffset,
+ type,
+ typedLength,
+ method,
+ });
+ this.eventualAsyncExpectation(async niceStack => {
+ const readback = await readbackPromise;
+ this.expectOK(check(readback.data), { mode, niceStack });
+ readback.cleanup();
+ });
+ }
+
+ /**
+ * Expect a GPUBuffer's contents to equal the values in the provided TypedArray.
+ */
+ expectGPUBufferValuesEqual(
+ src,
+ expected,
+ srcByteOffset = 0,
+ { method = 'copy', mode = 'fail' } = {}
+ ) {
+ this.expectGPUBufferValuesPassCheck(src, a => checkElementsEqual(a, expected), {
+ srcByteOffset,
+ type: expected.constructor,
+ typedLength: expected.length,
+ method,
+ mode,
+ });
+ }
+
+ /**
+ * Expect a buffer to consist exclusively of rows of some repeated expected value. The size of
+ * `expectedValue` must be 1, 2, or any multiple of 4 bytes. Rows in the buffer are expected to be
+ * zero-padded out to `bytesPerRow`. `minBytesPerRow` is the number of bytes per row that contain
+ * actual (non-padding) data and must be an exact multiple of the byte-length of `expectedValue`.
+ */
+ expectGPUBufferRepeatsSingleValue(
+ buffer,
+ { expectedValue, numRows, minBytesPerRow, bytesPerRow }
+ ) {
+ const valueSize = expectedValue.byteLength;
+ assert(valueSize === 1 || valueSize === 2 || valueSize % 4 === 0);
+ assert(minBytesPerRow % valueSize === 0);
+ assert(bytesPerRow % 4 === 0);
+
+ // If the buffer is small enough, just generate the full expected buffer contents and check
+ // against them on the CPU.
+ const kMaxBufferSizeToCheckOnCpu = 256 * 1024;
+ const bufferSize = bytesPerRow * (numRows - 1) + minBytesPerRow;
+ if (bufferSize <= kMaxBufferSizeToCheckOnCpu) {
+ const valueBytes = Array.from(new Uint8Array(expectedValue));
+ const rowValues = new Array(minBytesPerRow / valueSize).fill(valueBytes);
+ const rowBytes = new Uint8Array([].concat(...rowValues));
+ const expectedContents = new Uint8Array(bufferSize);
+ range(numRows, row => expectedContents.set(rowBytes, row * bytesPerRow));
+ this.expectGPUBufferValuesEqual(buffer, expectedContents);
+ return;
+ }
+
+ // Copy into a buffer suitable for STORAGE usage.
+ const storageBuffer = this.device.createBuffer({
+ size: bufferSize,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(storageBuffer);
+
+ // This buffer conveys the data we expect to see for a single value read. Since we read 32 bits at
+ // a time, for values smaller than 32 bits we pad this expectation with repeated value data, or
+ // with zeroes if the width of a row in the buffer is less than 4 bytes. For value sizes larger
+ // than 32 bits, we assume they're a multiple of 32 bits and expect to read exact matches of
+ // `expectedValue` as-is.
+ const expectedDataSize = Math.max(4, valueSize);
+ const expectedDataBuffer = this.device.createBuffer({
+ size: expectedDataSize,
+ usage: GPUBufferUsage.STORAGE,
+ mappedAtCreation: true,
+ });
+ this.trackForCleanup(expectedDataBuffer);
+ const expectedData = new Uint32Array(expectedDataBuffer.getMappedRange());
+ if (valueSize === 1) {
+ const value = new Uint8Array(expectedValue)[0];
+ const values = new Array(Math.min(4, minBytesPerRow)).fill(value);
+ const padding = new Array(Math.max(0, 4 - values.length)).fill(0);
+ const expectedBytes = new Uint8Array(expectedData.buffer);
+ expectedBytes.set([...values, ...padding]);
+ } else if (valueSize === 2) {
+ const value = new Uint16Array(expectedValue)[0];
+ const expectedWords = new Uint16Array(expectedData.buffer);
+ expectedWords.set([value, minBytesPerRow > 2 ? value : 0]);
+ } else {
+ expectedData.set(new Uint32Array(expectedValue));
+ }
+ expectedDataBuffer.unmap();
+
+ // The output buffer has one 32-bit entry per buffer row. An entry's value will be 1 if every
+ // read from the corresponding row matches the expected data derived above, or 0 otherwise.
+ const resultBuffer = this.device.createBuffer({
+ size: numRows * 4,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ this.trackForCleanup(resultBuffer);
+
+ const readsPerRow = Math.ceil(minBytesPerRow / expectedDataSize);
+ const reducer = `
+ struct Buffer { data: array<u32>, };
+ @group(0) @binding(0) var<storage, read> expected: Buffer;
+ @group(0) @binding(1) var<storage, read> in: Buffer;
+ @group(0) @binding(2) var<storage, read_write> out: Buffer;
+ @compute @workgroup_size(1) fn reduce(
+ @builtin(global_invocation_id) id: vec3<u32>) {
+ let rowBaseIndex = id.x * ${bytesPerRow / 4}u;
+ let readSize = ${expectedDataSize / 4}u;
+ out.data[id.x] = 1u;
+ for (var i: u32 = 0u; i < ${readsPerRow}u; i = i + 1u) {
+ let elementBaseIndex = rowBaseIndex + i * readSize;
+ for (var j: u32 = 0u; j < readSize; j = j + 1u) {
+ if (in.data[elementBaseIndex + j] != expected.data[j]) {
+ out.data[id.x] = 0u;
+ return;
+ }
+ }
+ }
+ }
+ `;
+
+ const pipeline = this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({ code: reducer }),
+ entryPoint: 'reduce',
+ },
+ });
+
+ const bindGroup = this.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ { binding: 0, resource: { buffer: expectedDataBuffer } },
+ { binding: 1, resource: { buffer: storageBuffer } },
+ { binding: 2, resource: { buffer: resultBuffer } },
+ ],
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyBufferToBuffer(buffer, 0, storageBuffer, 0, bufferSize);
+ const pass = commandEncoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(numRows);
+ pass.end();
+ this.device.queue.submit([commandEncoder.finish()]);
+
+ const expectedResults = new Array(numRows).fill(1);
+ this.expectGPUBufferValuesEqual(resultBuffer, new Uint32Array(expectedResults));
+ }
+
+ // MAINTENANCE_TODO: add an expectContents for textures, which logs data: uris on failure
+
+ /**
+ * Expect a whole GPUTexture to have the single provided color.
+ */
+ expectSingleColor(src, format, { size, exp, dimension = '2d', slice = 0, layout }) {
+ format = resolvePerAspectFormat(format, layout?.aspect);
+ const { byteLength, minBytesPerRow, bytesPerRow, rowsPerImage, mipSize } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ layout
+ );
+
+ const rep = kTexelRepresentationInfo[format];
+ const expectedTexelData = rep.pack(rep.encode(exp));
+
+ const buffer = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(buffer);
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToBuffer(
+ {
+ texture: src,
+ mipLevel: layout?.mipLevel,
+ origin: { x: 0, y: 0, z: slice },
+ aspect: layout?.aspect,
+ },
+ { buffer, bytesPerRow, rowsPerImage },
+ mipSize
+ );
+
+ this.queue.submit([commandEncoder.finish()]);
+
+ this.expectGPUBufferRepeatsSingleValue(buffer, {
+ expectedValue: expectedTexelData,
+ numRows: rowsPerImage,
+ minBytesPerRow,
+ bytesPerRow,
+ });
+ }
+
+ /** Return a GPUBuffer that data are going to be written into. */
+ readSinglePixelFrom2DTexture(src, format, { x, y }, { slice = 0, layout }) {
+ const { byteLength, bytesPerRow, rowsPerImage } = getTextureSubCopyLayout(
+ format,
+ [1, 1],
+ layout
+ );
+
+ const buffer = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ this.trackForCleanup(buffer);
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToBuffer(
+ { texture: src, mipLevel: layout?.mipLevel, origin: { x, y, z: slice } },
+ { buffer, bytesPerRow, rowsPerImage },
+ [1, 1]
+ );
+
+ this.queue.submit([commandEncoder.finish()]);
+
+ return buffer;
+ }
+
+ /**
+ * Expect a single pixel of a 2D texture to have a particular byte representation.
+ *
+ * MAINTENANCE_TODO: Add check for values of depth/stencil, probably through sampling of shader
+ * MAINTENANCE_TODO: Can refactor this and expectSingleColor to use a similar base expect
+ */
+ expectSinglePixelIn2DTexture(
+ src,
+ format,
+ { x, y },
+ { exp, slice = 0, layout, generateWarningOnly = false }
+ ) {
+ const buffer = this.readSinglePixelFrom2DTexture(src, format, { x, y }, { slice, layout });
+ this.expectGPUBufferValuesEqual(buffer, exp, 0, {
+ mode: generateWarningOnly ? 'warn' : 'fail',
+ });
+ }
+
+ /**
+ * Take a single pixel of a 2D texture, interpret it using a TypedArray of the `expected` type,
+ * and expect each value in that array to be between the corresponding "expected" values
+ * (either `a[i] <= actual[i] <= b[i]` or `a[i] >= actual[i] => b[i]`).
+ */
+ expectSinglePixelBetweenTwoValuesIn2DTexture(
+ src,
+ format,
+ { x, y },
+ {
+ exp,
+ slice = 0,
+ layout,
+ generateWarningOnly = false,
+ checkElementsBetweenFn = (act, [a, b]) => checkElementsBetween(act, [i => a[i], i => b[i]]),
+ }
+ ) {
+ assert(exp[0].constructor === exp[1].constructor);
+ const constructor = exp[0].constructor;
+ assert(exp[0].length === exp[1].length);
+ const typedLength = exp[0].length;
+
+ const buffer = this.readSinglePixelFrom2DTexture(src, format, { x, y }, { slice, layout });
+ this.expectGPUBufferValuesPassCheck(buffer, a => checkElementsBetweenFn(a, exp), {
+ type: constructor,
+ typedLength,
+ mode: generateWarningOnly ? 'warn' : 'fail',
+ });
+ }
+
+ /**
+ * Equivalent to {@link expectSinglePixelBetweenTwoValuesIn2DTexture} but uses a special check func
+ * to interpret incoming values as float16
+ */
+ expectSinglePixelBetweenTwoValuesFloat16In2DTexture(
+ src,
+ format,
+ { x, y },
+ { exp, slice = 0, layout, generateWarningOnly = false }
+ ) {
+ this.expectSinglePixelBetweenTwoValuesIn2DTexture(
+ src,
+ format,
+ { x, y },
+ {
+ exp,
+ slice,
+ layout,
+ generateWarningOnly,
+ checkElementsBetweenFn: checkElementsFloat16Between,
+ }
+ );
+ }
+
+ /**
+ * Emulate a texture to buffer copy by using a compute shader
+ * to load texture value of a single pixel and write to a storage buffer.
+ * For sample count == 1, the buffer contains only one value of the sample.
+ * For sample count > 1, the buffer contains (N = sampleCount) values sorted
+ * in the order of their sample index [0, sampleCount - 1]
+ *
+ * This can be useful when the texture to buffer copy is not available to the texture format
+ * e.g. (depth24plus), or when the texture is multisampled.
+ *
+ * MAINTENANCE_TODO: extend to read multiple pixels with given origin and size.
+ *
+ * @returns storage buffer containing the copied value from the texture.
+ */
+ copySinglePixelTextureToBufferUsingComputePass(type, componentCount, textureView, sampleCount) {
+ const textureSrcCode =
+ sampleCount === 1
+ ? `@group(0) @binding(0) var src: texture_2d<${type}>;`
+ : `@group(0) @binding(0) var src: texture_multisampled_2d<${type}>;`;
+ const code = `
+ struct Buffer {
+ data: array<${type}>,
+ };
+
+ ${textureSrcCode}
+ @group(0) @binding(1) var<storage, read_write> dst : Buffer;
+
+ @compute @workgroup_size(1) fn main() {
+ var coord = vec2<i32>(0, 0);
+ for (var sampleIndex = 0; sampleIndex < ${sampleCount};
+ sampleIndex = sampleIndex + 1) {
+ let o = sampleIndex * ${componentCount};
+ let v = textureLoad(src, coord, sampleIndex);
+ for (var component = 0; component < ${componentCount}; component = component + 1) {
+ dst.data[o + component] = v[component];
+ }
+ }
+ }
+ `;
+ const computePipeline = this.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: this.device.createShaderModule({
+ code,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const storageBuffer = this.device.createBuffer({
+ size: sampleCount * type.size * componentCount,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
+ });
+ this.trackForCleanup(storageBuffer);
+
+ const uniformBindGroup = this.device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: textureView,
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: storageBuffer,
+ },
+ },
+ ],
+ });
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(computePipeline);
+ pass.setBindGroup(0, uniformBindGroup);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ return storageBuffer;
+ }
+
+ /**
+ * Expect the specified WebGPU error to be generated when running the provided function.
+ */
+ expectGPUError(filter, fn, shouldError = true) {
+ // If no error is expected, we let the scope surrounding the test catch it.
+ if (!shouldError) {
+ return fn();
+ }
+
+ this.device.pushErrorScope(filter);
+ const returnValue = fn();
+ const promise = this.device.popErrorScope();
+
+ this.eventualAsyncExpectation(async niceStack => {
+ const error = await promise;
+
+ let failed = false;
+ switch (filter) {
+ case 'out-of-memory':
+ failed = !(error instanceof GPUOutOfMemoryError);
+ break;
+ case 'validation':
+ failed = !(error instanceof GPUValidationError);
+ break;
+ }
+
+ if (failed) {
+ niceStack.message = `Expected ${filter} error`;
+ this.rec.expectationFailed(niceStack);
+ } else {
+ niceStack.message = `Captured ${filter} error`;
+ if (error instanceof GPUValidationError) {
+ niceStack.message += ` - ${error.message}`;
+ }
+ this.rec.debug(niceStack);
+ }
+ });
+
+ return returnValue;
+ }
+
+ /**
+ * Expect a validation error inside the callback.
+ *
+ * Tests should always do just one WebGPU call in the callback, to make sure that's what's tested.
+ */
+ expectValidationError(fn, shouldError = true) {
+ // If no error is expected, we let the scope surrounding the test catch it.
+ if (shouldError) {
+ this.device.pushErrorScope('validation');
+ }
+
+ // Note: A return value is not allowed for the callback function. This is to avoid confusion
+ // about what the actual behavior would be; either of the following could be reasonable:
+ // - Make expectValidationError async, and have it await on fn(). This causes an async split
+ // between pushErrorScope and popErrorScope, so if the caller doesn't `await` on
+ // expectValidationError (either accidentally or because it doesn't care to do so), then
+ // other test code will be (nondeterministically) caught by the error scope.
+ // - Make expectValidationError NOT await fn(), but just execute its first block (until the
+ // first await) and return the return value (a Promise). This would be confusing because it
+ // would look like the error scope includes the whole async function, but doesn't.
+ // If we do decide we need to return a value, we should use the latter semantic.
+ const returnValue = fn();
+ assert(
+ returnValue === undefined,
+ 'expectValidationError callback should not return a value (or be async)'
+ );
+
+ if (shouldError) {
+ const promise = this.device.popErrorScope();
+
+ this.eventualAsyncExpectation(async niceStack => {
+ const gpuValidationError = await promise;
+ if (!gpuValidationError) {
+ niceStack.message = 'Validation succeeded unexpectedly.';
+ this.rec.validationFailed(niceStack);
+ } else if (gpuValidationError instanceof GPUValidationError) {
+ niceStack.message = `Validation failed, as expected - ${gpuValidationError.message}`;
+ this.rec.debug(niceStack);
+ }
+ });
+ }
+ }
+
+ /**
+ * Expects that the device should be lost for a particular reason at the teardown of the test.
+ */
+ expectDeviceLost(reason) {
+ assert(this.provider !== undefined, 'internal error: GPUDevice missing?');
+ this.provider.expectDeviceLost(reason);
+ }
+
+ /**
+ * Create a GPUBuffer with the specified contents and usage.
+ *
+ * MAINTENANCE_TODO: Several call sites would be simplified if this took ArrayBuffer as well.
+ */
+ makeBufferWithContents(dataArray, usage) {
+ return this.trackForCleanup(makeBufferWithContents(this.device, dataArray, usage));
+ }
+
+ /**
+ * Creates a texture with the contents of a TexelView.
+ */
+ makeTextureWithContents(texelView, desc) {
+ return this.trackForCleanup(makeTextureWithContents(this.device, texelView, desc));
+ }
+
+ /**
+ * Create a GPUTexture with multiple mip levels, each having the specified contents.
+ */
+ createTexture2DWithMipmaps(mipmapDataArray) {
+ const format = 'rgba8unorm';
+ const mipLevelCount = mipmapDataArray.length;
+ const textureSizeMipmap0 = 1 << (mipLevelCount - 1);
+ const texture = this.device.createTexture({
+ mipLevelCount,
+ size: { width: textureSizeMipmap0, height: textureSizeMipmap0, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
+ });
+ this.trackForCleanup(texture);
+
+ const textureEncoder = this.device.createCommandEncoder();
+ for (let i = 0; i < mipLevelCount; i++) {
+ const { byteLength, bytesPerRow, rowsPerImage, mipSize } = getTextureCopyLayout(
+ format,
+ '2d',
+ [textureSizeMipmap0, textureSizeMipmap0, 1],
+ { mipLevel: i }
+ );
+
+ const data = new Uint8Array(byteLength);
+ const mipLevelData = mipmapDataArray[i];
+ assert(rowsPerImage === mipSize[0]); // format is rgba8unorm and block size should be 1
+ for (let r = 0; r < rowsPerImage; r++) {
+ const o = r * bytesPerRow;
+ for (let c = o, end = o + mipSize[1] * 4; c < end; c += 4) {
+ data[c] = mipLevelData[0];
+ data[c + 1] = mipLevelData[1];
+ data[c + 2] = mipLevelData[2];
+ data[c + 3] = mipLevelData[3];
+ }
+ }
+ const buffer = this.makeBufferWithContents(
+ data,
+ GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
+ );
+
+ textureEncoder.copyBufferToTexture(
+ { buffer, bytesPerRow, rowsPerImage },
+ { texture, mipLevel: i, origin: [0, 0, 0] },
+ mipSize
+ );
+ }
+ this.device.queue.submit([textureEncoder.finish()]);
+
+ return texture;
+ }
+
+ /**
+ * Returns a GPUCommandEncoder, GPUComputePassEncoder, GPURenderPassEncoder, or
+ * GPURenderBundleEncoder, and a `finish` method returning a GPUCommandBuffer.
+ * Allows testing methods which have the same signature across multiple encoder interfaces.
+ *
+ * @example
+ * ```
+ * g.test('popDebugGroup')
+ * .params(u => u.combine('encoderType', kEncoderTypes))
+ * .fn(t => {
+ * const { encoder, finish } = t.createEncoder(t.params.encoderType);
+ * encoder.popDebugGroup();
+ * });
+ *
+ * g.test('writeTimestamp')
+ * .params(u => u.combine('encoderType', ['non-pass', 'compute pass', 'render pass'] as const)
+ * .fn(t => {
+ * const { encoder, finish } = t.createEncoder(t.params.encoderType);
+ * // Encoder type is inferred, so `writeTimestamp` can be used even though it doesn't exist
+ * // on GPURenderBundleEncoder.
+ * encoder.writeTimestamp(args);
+ * });
+ * ```
+ */
+ createEncoder(encoderType, { attachmentInfo, occlusionQuerySet } = {}) {
+ const fullAttachmentInfo = {
+ // Defaults if not overridden:
+ colorFormats: ['rgba8unorm'],
+ sampleCount: 1,
+ // Passed values take precedent.
+ ...attachmentInfo,
+ };
+
+ switch (encoderType) {
+ case 'non-pass': {
+ const encoder = this.device.createCommandEncoder();
+
+ return new CommandBufferMaker(this, encoder, () => {
+ return encoder.finish();
+ });
+ }
+ case 'render bundle': {
+ const device = this.device;
+ const rbEncoder = device.createRenderBundleEncoder(fullAttachmentInfo);
+ const pass = this.createEncoder('render pass', { attachmentInfo });
+
+ return new CommandBufferMaker(this, rbEncoder, () => {
+ pass.encoder.executeBundles([rbEncoder.finish()]);
+ return pass.finish();
+ });
+ }
+ case 'compute pass': {
+ const commandEncoder = this.device.createCommandEncoder();
+ const encoder = commandEncoder.beginComputePass();
+
+ return new CommandBufferMaker(this, encoder, () => {
+ encoder.end();
+ return commandEncoder.finish();
+ });
+ }
+ case 'render pass': {
+ const makeAttachmentView = format =>
+ this.trackForCleanup(
+ this.device.createTexture({
+ size: [16, 16, 1],
+ format,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ sampleCount: fullAttachmentInfo.sampleCount,
+ })
+ ).createView();
+
+ let depthStencilAttachment = undefined;
+ if (fullAttachmentInfo.depthStencilFormat !== undefined) {
+ depthStencilAttachment = {
+ view: makeAttachmentView(fullAttachmentInfo.depthStencilFormat),
+ depthReadOnly: fullAttachmentInfo.depthReadOnly,
+ stencilReadOnly: fullAttachmentInfo.stencilReadOnly,
+ };
+ if (
+ kTextureFormatInfo[fullAttachmentInfo.depthStencilFormat].depth &&
+ !fullAttachmentInfo.depthReadOnly
+ ) {
+ depthStencilAttachment.depthClearValue = 0;
+ depthStencilAttachment.depthLoadOp = 'clear';
+ depthStencilAttachment.depthStoreOp = 'discard';
+ }
+ if (
+ kTextureFormatInfo[fullAttachmentInfo.depthStencilFormat].stencil &&
+ !fullAttachmentInfo.stencilReadOnly
+ ) {
+ depthStencilAttachment.stencilClearValue = 1;
+ depthStencilAttachment.stencilLoadOp = 'clear';
+ depthStencilAttachment.stencilStoreOp = 'discard';
+ }
+ }
+ const passDesc = {
+ colorAttachments: Array.from(fullAttachmentInfo.colorFormats, format =>
+ format
+ ? {
+ view: makeAttachmentView(format),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ }
+ : null
+ ),
+
+ depthStencilAttachment,
+ occlusionQuerySet,
+ };
+
+ const commandEncoder = this.device.createCommandEncoder();
+ const encoder = commandEncoder.beginRenderPass(passDesc);
+ return new CommandBufferMaker(this, encoder, () => {
+ encoder.end();
+ return commandEncoder.finish();
+ });
+ }
+ }
+
+ unreachable();
+ }
+}
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
new file mode 100644
index 0000000000..3002c49b23
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/constants/flags.spec.js
@@ -0,0 +1,80 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test the values of flags interfaces (e.g. GPUTextureUsage).
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { IDLTest } from '../idl_test.js';
+
+export const g = makeTestGroup(IDLTest);
+
+const kBufferUsageExp = {
+ MAP_READ: 0x0001,
+ MAP_WRITE: 0x0002,
+ COPY_SRC: 0x0004,
+ COPY_DST: 0x0008,
+ INDEX: 0x0010,
+ VERTEX: 0x0020,
+ UNIFORM: 0x0040,
+ STORAGE: 0x0080,
+ INDIRECT: 0x0100,
+ QUERY_RESOLVE: 0x0200,
+};
+g.test('BufferUsage,count').fn(t => {
+ t.assertMemberCount(GPUBufferUsage, kBufferUsageExp);
+});
+g.test('BufferUsage,values')
+ .params(u => u.combine('key', Object.keys(kBufferUsageExp)))
+ .fn(t => {
+ const { key } = t.params;
+ t.assertMember(GPUBufferUsage, kBufferUsageExp, key);
+ });
+
+const kTextureUsageExp = {
+ COPY_SRC: 0x01,
+ COPY_DST: 0x02,
+ TEXTURE_BINDING: 0x04,
+ STORAGE_BINDING: 0x08,
+ RENDER_ATTACHMENT: 0x10,
+};
+g.test('TextureUsage,count').fn(t => {
+ t.assertMemberCount(GPUTextureUsage, kTextureUsageExp);
+});
+g.test('TextureUsage,values')
+ .params(u => u.combine('key', Object.keys(kTextureUsageExp)))
+ .fn(t => {
+ const { key } = t.params;
+ t.assertMember(GPUTextureUsage, kTextureUsageExp, key);
+ });
+
+const kColorWriteExp = {
+ RED: 0x1,
+ GREEN: 0x2,
+ BLUE: 0x4,
+ ALPHA: 0x8,
+ ALL: 0xf,
+};
+g.test('ColorWrite,count').fn(t => {
+ t.assertMemberCount(GPUColorWrite, kColorWriteExp);
+});
+g.test('ColorWrite,values')
+ .params(u => u.combine('key', Object.keys(kColorWriteExp)))
+ .fn(t => {
+ const { key } = t.params;
+ t.assertMember(GPUColorWrite, kColorWriteExp, key);
+ });
+
+const kShaderStageExp = {
+ VERTEX: 0x1,
+ FRAGMENT: 0x2,
+ COMPUTE: 0x4,
+};
+g.test('ShaderStage,count').fn(t => {
+ t.assertMemberCount(GPUShaderStage, kShaderStageExp);
+});
+g.test('ShaderStage,values')
+ .params(u => u.combine('key', Object.keys(kShaderStageExp)))
+ .fn(t => {
+ const { key } = t.params;
+ t.assertMember(GPUShaderStage, kShaderStageExp, key);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.html.js
new file mode 100644
index 0000000000..7ac9f2ef50
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.html.js
@@ -0,0 +1,52 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // WPT-specific test checking that WebGPU is available iff isSecureContext.
+import { assert } from '../../common/util/util.js';
+const items = [
+ globalThis.navigator.gpu,
+ globalThis.GPU,
+ globalThis.GPUAdapter,
+ globalThis.GPUAdapterInfo,
+ globalThis.GPUBindGroup,
+ globalThis.GPUBindGroupLayout,
+ globalThis.GPUBuffer,
+ globalThis.GPUBufferUsage,
+ globalThis.GPUCanvasContext,
+ globalThis.GPUColorWrite,
+ globalThis.GPUCommandBuffer,
+ globalThis.GPUCommandEncoder,
+ globalThis.GPUCompilationInfo,
+ globalThis.GPUCompilationMessage,
+ globalThis.GPUComputePassEncoder,
+ globalThis.GPUComputePipeline,
+ globalThis.GPUDevice,
+ globalThis.GPUDeviceLostInfo,
+ globalThis.GPUError,
+ globalThis.GPUExternalTexture,
+ globalThis.GPUMapMode,
+ globalThis.GPUOutOfMemoryError,
+ globalThis.GPUPipelineLayout,
+ globalThis.GPUQuerySet,
+ globalThis.GPUQueue,
+ globalThis.GPURenderBundle,
+ globalThis.GPURenderBundleEncoder,
+ globalThis.GPURenderPassEncoder,
+ globalThis.GPURenderPipeline,
+ globalThis.GPUSampler,
+ globalThis.GPUShaderModule,
+ globalThis.GPUShaderStage,
+ globalThis.GPUSupportedLimits,
+ globalThis.GPUTexture,
+ globalThis.GPUTextureUsage,
+ globalThis.GPUTextureView,
+ globalThis.GPUUncapturedErrorEvent,
+ globalThis.GPUValidationError,
+];
+
+for (const item of items) {
+ if (globalThis.isSecureContext) {
+ assert(item !== undefined, 'Item/interface should be exposed on secure context');
+ } else {
+ assert(item === undefined, 'Item/interface should not be exposed on insecure context');
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html
new file mode 100644
index 0000000000..589460d499
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.http.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>WebGPU exposed items (non-HTTPS)</title>
+ <meta name=assert content="WebGPU should not be exposed on a non-[SecureContext]">
+ <link rel=help href='https://gpuweb.github.io/gpuweb/'>
+ <script type=module src=exposed.html.js></script>
+ </head>
+ <body></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html
new file mode 100644
index 0000000000..6b369f07ca
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/exposed.https.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html>
+ <head>
+ <title>WebGPU exposed items (HTTPS)</title>
+ <meta charset=utf-8>
+ <meta name=assert content="All specified WebGPU items/interfaces should be exposed, on a [SecureContext]">
+ <link rel=help href='https://gpuweb.github.io/gpuweb/'>
+ <script type=module src=exposed.html.js></script>
+ </head>
+ <body></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/idl_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/idl_test.js
new file mode 100644
index 0000000000..6d6f684c9c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/idl/idl_test.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { Fixture } from '../../common/framework/fixture.js';
+import { getGPU } from '../../common/util/navigator_gpu.js';
+import { assert } from '../../common/util/util.js';
+
+/**
+ * Base fixture for testing the exposed interface is correct (without actually using WebGPU).
+ */
+export class IDLTest extends Fixture {
+ async init() {
+ // Ensure the GPU provider is initialized
+ getGPU();
+ }
+
+ /**
+ * Asserts that a member of an IDL interface has the expected value.
+ */
+ assertMember(act, exp, key) {
+ assert(key in act, () => `Expected key ${key} missing`);
+ assert(act[key] === exp[key], () => `Value of [${key}] was ${act[key]}, expected ${exp[key]}`);
+ }
+
+ /**
+ * Asserts that an IDL interface has the same number of keys as the
+ *
+ * MAINTENANCE_TODO: add a way to check for the types of keys with unknown values, like methods and attributes
+ * MAINTENANCE_TODO: handle extensions
+ */
+ assertMemberCount(act, exp) {
+ const expKeys = Object.keys(exp);
+ const actKeys = Object.keys(act);
+ assert(
+ actKeys.length === expKeys.length,
+ () => `Had ${actKeys.length} keys, expected ${expKeys.length}`
+ );
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js
new file mode 100644
index 0000000000..b00e1cc0b8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/listing.js
@@ -0,0 +1,2829 @@
+// AUTO-GENERATED - DO NOT EDIT. See src/common/tools/gen_listings.ts.
+
+export const listing = [
+ {
+ "file": [],
+ "readme": "WebGPU conformance test suite."
+ },
+ {
+ "file": [
+ "api"
+ ],
+ "readme": "Tests for full coverage of the Javascript API surface of WebGPU."
+ },
+ {
+ "file": [
+ "api",
+ "operation"
+ ],
+ "readme": "Tests that check the result of performing valid WebGPU operations, taking advantage of\nparameterization to exercise interactions between features."
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "adapter",
+ "requestAdapter"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "adapter",
+ "requestAdapterInfo"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "adapter",
+ "requestDevice"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "async_ordering"
+ ],
+ "readme": "Test ordering of async resolutions between promises returned by the following calls (and possibly\nbetween multiple of the same call), where there are constraints on the ordering.\nSpec issue: https://github.com/gpuweb/gpuweb/issues/962\n\nTODO: plan and implement\n- createReadyPipeline() (not sure if this actually has any ordering constraints)\n- cmdbuf.executionTime\n- device.popErrorScope()\n- device.lost\n- queue.onSubmittedWorkDone()\n- buffer.mapAsync()\n- shadermodule.compilationInfo()"
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers"
+ ],
+ "readme": "GPUBuffer tests."
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers",
+ "map"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers",
+ "map_ArrayBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers",
+ "map_detach"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers",
+ "map_oom"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "buffers",
+ "threading"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "basic"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "clearBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "copyBufferToBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "copyTextureToTexture"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "image_copy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "programmable",
+ "state_tracking"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "queries"
+ ],
+ "readme": "TODO: test the behavior of creating/using/resolving queries.\n- occlusion\n- pipeline statistics\n TODO: pipeline statistics queries are removed from core; consider moving tests to another suite.\n- timestamp\n- nested (e.g. timestamp or PS query inside occlusion query), if any such cases are valid. Try\n writing to the same query set (at same or different indices), if valid. Check results make sense.\n- start a query (all types) with no draw calls"
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "render",
+ "dynamic_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "command_buffer",
+ "render",
+ "state_tracking"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "compute",
+ "basic"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "compute_pipeline",
+ "entry_point_name"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "compute_pipeline",
+ "overrides"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "device",
+ "lost"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "labels"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "memory_allocation"
+ ],
+ "readme": "Try to stress memory allocators in the implementation and driver.\n\nTODO: plan and implement\n- Tests which (pseudo-randomly?) allocate a bunch of memory and then assert things about the memory\n (it's not aliased, it's valid to read and write in various ways, accesses read/write the correct data)\n - Possibly also with OOB accesses/robust buffer access?\n- Tests which are targeted against particular known implementation details"
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "memory_sync",
+ "buffer",
+ "multiple_buffers"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "memory_sync",
+ "buffer",
+ "single_buffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "memory_sync",
+ "texture",
+ "same_subresource"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "onSubmittedWorkDone"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "pipeline",
+ "default_layout"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "queue",
+ "writeBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "reflection"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pass"
+ ],
+ "readme": "Render pass stuff other than commands (which are in command_buffer/)."
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pass",
+ "clear_value"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pass",
+ "resolve"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pass",
+ "storeOp"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pass",
+ "storeop2"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "alpha_to_coverage"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "culling_tests"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "overrides"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "pipeline_output_targets"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "primitive_topology"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "sample_mask"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "render_pipeline",
+ "vertex_only_render_pipeline"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "basic"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "color_target_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "depth"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "depth_bias"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "depth_clip_clamp"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "draw"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "indirect_draw"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "robust_access_index"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "rendering",
+ "stencil"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "resource_init",
+ "buffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "resource_init",
+ "texture_zero"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "sampling",
+ "anisotropy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "sampling",
+ "filter_mode"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "sampling",
+ "lod_clamp"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "shader_module",
+ "compilation_info"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "texture_view",
+ "format_reinterpretation"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "texture_view",
+ "read"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "texture_view",
+ "write"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "threading"
+ ],
+ "readme": "Tests for behavior with multiple threads (main thread + workers).\n\nTODO: plan and implement\n- 'postMessage'\n Try postMessage'ing an object of every type (to same or different thread)\n - {main -> main, main -> worker, worker -> main, worker1 -> worker1, worker1 -> worker2}\n - through {global postMessage, MessageChannel}\n - {in, not in} transferrable object list, when valid\n- 'concurrency'\n Short tight loop doing many of an action from two threads at the same time\n - e.g. {create {buffer, texture, shader, pipeline}}"
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "uncapturederror"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "vertex_state",
+ "correctness"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "operation",
+ "vertex_state",
+ "index_format"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "regression"
+ ],
+ "readme": "One-off tests that reproduce API bugs found in implementations to prevent the bugs from\nappearing again."
+ },
+ {
+ "file": [
+ "api",
+ "validation"
+ ],
+ "readme": "Positive and negative tests for all the validation rules of the API."
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "buffer",
+ "create"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "buffer",
+ "destroy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "buffer",
+ "mapping"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "buffer",
+ "threading"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "capability_checks",
+ "features"
+ ],
+ "readme": "Test every method or option that shouldn't be allowed without a feature enabled.\nIf the feature is not enabled, any use of an enum value added by a feature must be an\n*exception*, per <https://github.com/gpuweb/gpuweb/blob/main/design/ErrorConventions.md>.\n\n- x= that feature {enabled, disabled}\n\nGenerally one file for each feature name, but some may be grouped (e.g. one file for all optional\nquery types, one file for all optional texture formats).\n\nTODO: implement"
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "capability_checks",
+ "features",
+ "query_types"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "capability_checks",
+ "features",
+ "texture_formats"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "capability_checks",
+ "limits"
+ ],
+ "readme": "Test everything that shouldn't be valid without a higher-than-specified limit.\n\n- x= that limit {default, max supported (if different), lower than default (TODO: if allowed)}\n\nOne file for each limit name.\n\nTODO: implement\nTODO: Also test that \"alignment\" limits require a power of 2."
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "compute_pipeline"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createBindGroup"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createBindGroupLayout"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createPipelineLayout"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createSampler"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createTexture"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "createView"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "debugMarker"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "beginComputePass"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "beginRenderPass"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "clearBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "compute_pass"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "copyBufferToBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "copyTextureToTexture"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "debug"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "index_access"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "draw"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "dynamic_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "indirect_draw"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "setIndexBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "setPipeline"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "setVertexBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render",
+ "state_tracking"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "render_pass"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "cmds",
+ "setBindGroup"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "createRenderBundleEncoder"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "encoder_open_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "encoder_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "programmable",
+ "pipeline_bind_group_compat"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "queries",
+ "begin_end"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "queries",
+ "general"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "queries",
+ "pipeline_statistics"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "queries",
+ "resolveQuerySet"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "encoding",
+ "render_bundle"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "error_scope"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "getBindGroupLayout"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "image_copy"
+ ],
+ "readme": "writeTexture + copyBufferToTexture + copyTextureToBuffer validation tests.\n\nTest coverage:\n* resource usages:\n\t- texture_usage_must_be_valid: for GPUTextureUsage::COPY_SRC, GPUTextureUsage::COPY_DST flags.\n\t- buffer_usage_must_be_valid: for GPUBufferUsage::COPY_SRC, GPUBufferUsage::COPY_DST flags.\n\n* textureCopyView:\n\t- texture_must_be_valid: for valid, destroyed, error textures.\n\t- sample_count_must_be_1: for sample count 1 and 4.\n\t- mip_level_must_be_in_range: for various combinations of mipLevel and mipLevelCount.\n\t- format: for all formats with full and non-full copies on width, height, and depth.\n\t- texel_block_alignment_on_origin: for all formats and coordinates.\n\n* bufferCopyView:\n\t- buffer_must_be_valid: for valid, destroyed, error buffers.\n\t- bytes_per_row_alignment: for bytesPerRow to be 256-byte aligned or not, and bytesPerRow is required or not.\n\n* linear texture data:\n\t- bound_on_rows_per_image: for various combinations of copyDepth (1, >1), copyHeight, rowsPerImage.\n\t- offset_plus_required_bytes_in_copy_overflow\n\t- required_bytes_in_copy: testing minimal data size and data size too small for various combinations of bytesPerRow, rowsPerImage, copyExtent and offset. for the copy method, bytesPerRow is computed as bytesInACompleteRow aligned to be a multiple of 256 + bytesPerRowPadding * 256.\n\t- texel_block_alignment_on_rows_per_image: for all formats.\n\t- offset_alignment: for all formats.\n\t- bound_on_offset: for various combinations of offset and dataSize.\n\n* texture copy range:\n\t- 1d_texture: copyExtent.height isn't 1, copyExtent.depthOrArrayLayers isn't 1.\n\t- texel_block_alignment_on_size: for all formats and coordinates.\n\t- texture_range_conditons: for all coordinate and various combinations of origin, copyExtent, textureSize and mipLevel.\n\nTODO: more test coverage for 1D and 3D textures."
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "image_copy",
+ "buffer_related"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "image_copy",
+ "buffer_texture_copies"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "image_copy",
+ "layout_related"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "image_copy",
+ "texture_related"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "layout_shader_compat"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "query_set",
+ "create"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "query_set",
+ "destroy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue"
+ ],
+ "readme": "Tests for validation that occurs inside queued operations\n(submit, writeBuffer, writeTexture, copyExternalImageToTexture).\n\nBufferMapStatesToTest = {\n mapped -> unmapped,\n mapped at creation -> unmapped,\n mapping pending -> unmapped,\n pending -> mapped (await map),\n unmapped -> pending (noawait map),\n created mapped-at-creation,\n}\n\nNote writeTexture is tested in image_copy."
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "buffer_mapped"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "copyToTexture",
+ "CopyExternalImageToTexture"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "destroyed",
+ "query_set"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "submit"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "writeBuffer"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "queue",
+ "writeTexture"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pass"
+ ],
+ "readme": "Render pass stuff other than commands (which are in encoding/cmds/)."
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pass",
+ "attachment_compatibility"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pass",
+ "render_pass_descriptor"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pass",
+ "resolve"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pass",
+ "storeOp"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "depth_stencil_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "fragment_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "inter_stage"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "misc"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "multisample_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "overrides"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "primitive_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "shader_module"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "render_pipeline",
+ "vertex_state"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "buffer"
+ ],
+ "readme": "TODO: look at texture,*"
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "buffer",
+ "in_pass_encoder"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "buffer",
+ "in_pass_misc"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "texture",
+ "in_pass_encoder"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "texture",
+ "in_render_common"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "resource_usages",
+ "texture",
+ "in_render_misc"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "shader_module",
+ "entry_point"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "shader_module",
+ "overrides"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "state",
+ "device_lost"
+ ],
+ "readme": "Tests of behavior while the device is lost.\n\n- x= every method in the API.\n\nTODO: implement"
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "state",
+ "device_lost",
+ "destroy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "texture",
+ "destroy"
+ ]
+ },
+ {
+ "file": [
+ "api",
+ "validation",
+ "texture",
+ "rg11b10ufloat_renderable"
+ ]
+ },
+ {
+ "file": [
+ "examples"
+ ]
+ },
+ {
+ "file": [
+ "idl"
+ ],
+ "readme": "Tests to check that the WebGPU IDL is correctly implemented, for examples that objects exposed\nexactly the correct members, and that methods throw when passed incomplete dictionaries.\n\nSee https://github.com/gpuweb/cts/issues/332\n\nTODO: exposed.html.ts: Test all WebGPU interfaces instead of just some of them.\nTODO: Check prototype chains. (Add a helper in IDLTest for this.)"
+ },
+ {
+ "file": [
+ "idl",
+ "constants",
+ "flags"
+ ]
+ },
+ {
+ "file": [
+ "shader"
+ ],
+ "readme": "Tests for full coverage of the shaders that can be passed to WebGPU."
+ },
+ {
+ "file": [
+ "shader",
+ "execution"
+ ],
+ "readme": "Tests that check the result of valid shader execution."
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "evaluation_order"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "bitwise"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "bool_logical"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "f32_arithmetic"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "f32_logical"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "i32_arithmetic"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "binary",
+ "u32_arithmetic"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "abs"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "acos"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "acosh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "all"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "any"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "arrayLength"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "asin"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "asinh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atan"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atan2"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atanh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicAdd"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicAnd"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicCompareExchangeWeak"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicExchange"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicLoad"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicMax"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicMin"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicOr"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicStore"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicSub"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "atomicXor"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "ceil"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "clamp"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "cos"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "cosh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "countLeadingZeros"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "countOneBits"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "countTrailingZeros"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "cross"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "degrees"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "determinant"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "distance"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dot"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdx"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdxCoarse"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdxFine"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdy"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdyCoarse"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "dpdyFine"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "exp"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "exp2"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "extractBits"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "faceForward"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "firstLeadingBit"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "firstTrailingBit"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "floor"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "fma"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "fract"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "frexp"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "fwidth"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "fwidthCoarse"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "fwidthFine"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "insertBits"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "inversesqrt"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "ldexp"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "length"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "log"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "log2"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "max"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "min"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "mix"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "modf"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "normalize"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pack2x16float"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pack2x16snorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pack2x16unorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pack4x8snorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pack4x8unorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "pow"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "quantizeToF16"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "radians"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "reflect"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "refract"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "reverseBits"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "round"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "saturate"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "select"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "sign"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "sin"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "sinh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "smoothstep"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "sqrt"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "step"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "storageBarrier"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "tan"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "tanh"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureDimension"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureGather"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureGatherCompare"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureLoad"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureNumLayers"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureNumLevels"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureNumSamples"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSample"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSampleBias"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSampleCompare"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSampleCompareLevel"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSampleGrad"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureSampleLevel"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "textureStore"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "transpose"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "trunc"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "unpack2x16float"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "unpack2x16snorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "unpack2x16unorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "unpack4x8snorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "unpack4x8unorm"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "call",
+ "builtin",
+ "workgroupBarrier"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "unary",
+ "bool_logical"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "unary",
+ "f32_arithmetic"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "expression",
+ "unary",
+ "i32_arithmetic"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "memory_model",
+ "atomicity"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "memory_model",
+ "barrier"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "memory_model",
+ "coherence"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "memory_model",
+ "weak"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "padding"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "robust_access"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "robust_access_vertex"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "shader_io",
+ "compute_builtins"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "shader_io",
+ "shared_structs"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "execution",
+ "zero_init"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "regression"
+ ],
+ "readme": "One-off tests that reproduce shader bugs found in implementations to prevent the bugs from\nappearing again."
+ },
+ {
+ "file": [
+ "shader",
+ "validation"
+ ],
+ "readme": "Positive and negative tests for all the validation rules of the shading language."
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "align"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "blankspace"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "builtin"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "comments"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "identifiers"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "literal"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "semicolon"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "source"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "static_assert"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "parse",
+ "var_and_let"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "resource_interface",
+ "bindings"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "shader_io",
+ "builtins"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "shader_io",
+ "entry_point"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "shader_io",
+ "interpolate"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "shader_io",
+ "invariant"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "shader_io",
+ "locations"
+ ]
+ },
+ {
+ "file": [
+ "shader",
+ "validation",
+ "static_assert",
+ "static_assert"
+ ]
+ },
+ {
+ "file": [
+ "util",
+ "texture",
+ "texel_data"
+ ]
+ },
+ {
+ "file": [
+ "util",
+ "texture",
+ "texture_ok"
+ ]
+ },
+ {
+ "file": [
+ "web_platform"
+ ],
+ "readme": "Tests for Web platform-specific interactions like GPUCanvasContext and canvas, WebXR,\nImageBitmaps, and video APIs.\n\nTODO(#922): Also hopefully tests for user-initiated readbacks from WebGPU canvases\n(printing, save image as, etc.)"
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas"
+ ],
+ "readme": "Tests for WebGPU <canvas> and OffscreenCanvas presentation."
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas",
+ "configure"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas",
+ "context_creation"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas",
+ "getCurrentTexture"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas",
+ "getPreferredCanvasFormat"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "canvas",
+ "readbackFromWebGPUCanvas"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "copyToTexture",
+ "ImageBitmap"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "copyToTexture"
+ ],
+ "readme": "Tests for copyToTexture from all possible sources (video, canvas, ImageBitmap, ...)"
+ },
+ {
+ "file": [
+ "web_platform",
+ "copyToTexture",
+ "canvas"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "copyToTexture",
+ "video"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "external_texture"
+ ],
+ "readme": "Tests for external textures."
+ },
+ {
+ "file": [
+ "web_platform",
+ "external_texture",
+ "video"
+ ]
+ },
+ {
+ "file": [
+ "web_platform",
+ "reftests"
+ ],
+ "readme": "Reference tests (reftests) for WebGPU canvas presentation.\n\nThese render some contents to a canvas using WebGPU, and WPT compares the rendering result with\nthe \"reference\" versions (in `ref/`) which render with 2D canvas.\n\nThis tests things like:\n- The canvas has the correct orientation.\n- The canvas renders with the correct transfer function.\n- The canvas blends and interpolates in the correct color encoding.\n\nTODO(#918): Test all possible color spaces (once we have more than 1)\nTODO(#921): Why is there sometimes a difference of 1 (e.g. 3f vs 40) in canvas_size_different_with_back_buffer_size?\nAnd why does chromium's image_diff show diffs on other pixels that don't seem to have diffs?\nTODO(#1093): Test rgba16float values which are out of gamut of the canvas but under SDR luminance.\nTODO(#1093): Test rgba16float values which are above SDR luminance.\nTODO(#1116): Test canvas scaling.\nTODO: Test transferControlToOffscreen, used from {the same,another} thread"
+ },
+ {
+ "file": [
+ "web_platform",
+ "worker",
+ "worker"
+ ]
+ }
+];
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/evaluation_order.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/evaluation_order.spec.js
new file mode 100644
index 0000000000..ec492fe1ba
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/evaluation_order.spec.js
@@ -0,0 +1,485 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for evaluation order of expressions
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { GPUTest } from '../../gpu_test.js';
+import { TypeI32 } from '../../util/conversion.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const common_source = `
+var<private> a : i32 = 2;
+var<private> b : i32 = 3;
+var<private> c : i32 = 4;
+
+var<private> arr2D : array<array<i32, 10>, 10> = array<array<i32, 10>, 10>(
+ array<i32, 10>( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+ array<i32, 10>(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
+ array<i32, 10>(20, 22, 22, 23, 24, 25, 26, 27, 28, 29),
+ array<i32, 10>(30, 32, 32, 33, 34, 35, 36, 37, 38, 33),
+ array<i32, 10>(40, 42, 42, 43, 44, 45, 46, 47, 48, 44),
+ array<i32, 10>(50, 52, 52, 53, 54, 55, 56, 57, 58, 55),
+ array<i32, 10>(60, 62, 62, 63, 64, 65, 66, 67, 68, 66),
+ array<i32, 10>(70, 72, 72, 73, 74, 75, 76, 77, 78, 77),
+ array<i32, 10>(80, 82, 82, 83, 84, 85, 86, 87, 88, 98),
+ array<i32, 10>(90, 92, 92, 93, 94, 95, 96, 97, 98, 99),
+);
+
+var<private> arr1D_zero : array<i32, 50>;
+var<private> arr2D_zero : array<array<i32, 50>, 50>;
+var<private> arr3D_zero : array<array<array<i32, 50>, 50>, 50>;
+
+var<private> vec4_zero : vec4<i32>;
+
+struct S {
+ x : i32,
+ y : i32,
+ z : i32,
+}
+
+fn mul(p1 : ptr<private, i32>, multiplicand : i32) -> i32 {
+ *p1 = *p1 * multiplicand;
+ return *p1;
+}
+
+fn add(p1 : ptr<private, i32>, addend : i32) -> i32 {
+ *p1 = *p1 + addend;
+ return *p1;
+}
+
+fn sub_mul3(a : i32, a_mul : i32, b : i32, b_mul : i32, c : i32, c_mul : i32) -> i32 {
+ return a * a_mul - b * b_mul - c * c_mul;
+}
+
+fn sub_mul4(a : i32, a_mul : i32, b : i32, b_mul : i32, c : i32, c_mul : i32, d : i32, d_mul : i32) -> i32 {
+ return a * a_mul - b * b_mul - c * c_mul - d * d_mul;
+}
+
+fn set_vec4_x(p : ptr<private, vec4<i32>>, v : i32) -> i32 {
+ (*p).x = v;
+ return 0;
+}
+
+fn make_S(init : i32) -> S {
+ return S(init, init, init);
+}
+
+fn mul3_ret0(p1 : ptr<private, i32>, p2 : ptr<private, i32>, p3 : ptr<private, i32>, multiplicand : i32) -> i32 {
+ *p1 = *p1 * multiplicand;
+ *p2 = *p2 * multiplicand;
+ *p3 = *p3 * multiplicand;
+ return 0;
+}
+`;
+
+g.test('binary_arith')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr')
+ .desc('Tests order of evaluation of arithmetic binary expressions.')
+ .paramsSimple([
+ {
+ name: 'BothSE', // SE = Side Effects
+ _body: 'return mul(&a, 10) - mul(&a, 10);',
+ _result: 20 - 200,
+ },
+ {
+ name: 'LeftSE', //
+ _body: 'return mul(&a, 10) - a;',
+ _result: 20 - 20,
+ },
+ {
+ name: 'RightSE', //
+ _body: 'return a - mul(&a, 10);',
+ _result: 2 - 20,
+ },
+ {
+ name: 'ThreeSE',
+ _body: 'return mul(&a, 10) - mul(&a, 10) - mul(&a, 10);',
+ _result: 20 - 200 - 2000,
+ },
+ {
+ name: 'LeftmostSE',
+ _body: 'return mul3_ret0(&a, &b, &c, 10) - a - b - c;',
+ _result: 0 - 20 - 30 - 40,
+ },
+ {
+ name: 'RightmostSE', //
+ _body: 'return a - b - c - mul3_ret0(&a, &b, &c, 10);',
+ _result: 2 - 3 - 4 - 0,
+ },
+ {
+ name: 'MiddleSE', //
+ _body: 'return a - b - mul3_ret0(&a, &b, &c, 10) - c;',
+ _result: 2 - 3 - 0 - 40,
+ },
+ {
+ name: 'LiteralAndSEAndVar', //
+ _body: 'return 1 - mul(&a, 10) - a;',
+ _result: 1 - 20 - 20,
+ },
+ {
+ name: 'VarAndSEAndLiteral', //
+ _body: 'return a - mul(&a, 10) - 1;',
+ _result: 2 - 20 - 1,
+ },
+ {
+ name: 'SEAndVarAndLiteral', //
+ _body: 'return mul(&a, 10) - a - 1;',
+ _result: 20 - 20 - 1,
+ },
+ {
+ name: 'VarAndLiteralAndSE', //
+ _body: 'return a - 1 - mul(&a, 10);',
+ _result: 2 - 1 - 20,
+ },
+ {
+ name: 'MemberAccessAndSE',
+ _body: 'return vec4_zero.x + set_vec4_x(&vec4_zero, 42);',
+ _result: 0,
+ },
+ {
+ name: 'SEAndMemberAccess',
+ _body: 'return set_vec4_x(&vec4_zero, 42) + vec4_zero.x;',
+ _result: 42,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('binary_logical')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#logical-expr')
+ .desc('Tests order of evaluation of logical binary expressions.')
+ .paramsSimple([
+ {
+ name: 'BothSE',
+ _body:
+ 'let r = (add(&a, 1) == 3) && (add(&a, 1) == 4);' + //
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'LeftSE',
+ _body:
+ 'let r = (add(&a, 1) == 3) && (a == 3);' + //
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'RightSE',
+ _body:
+ 'let r = (a == 2) && (add(&a, 1) == 3);' + //
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'LeftmostSE',
+ _body:
+ 'let r = (mul3_ret0(&a, &b, &c, 10) == 0) && (a == 20) && (b == 30) && (c == 40);' +
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'RightmostSE',
+ _body:
+ 'let r = (a == 2) && (b == 3) && (c == 4) && (mul3_ret0(&a, &b, &c, 10) == 0);' +
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'MiddleSE',
+ _body:
+ 'let r = (a == 2) && (b == 3) && (mul3_ret0(&a, &b, &c, 10) == 0) && (c == 40);' +
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'ShortCircuit_And_LhsOnly',
+ _body:
+ // rhs should not execute
+ 'let t = (a != 2) && (mul(&a, 10) == 20);' + //
+ 'return a;',
+ _result: 2,
+ },
+ {
+ name: 'ShortCircuit_And_LhsAndRhs',
+ _body:
+ // rhs should execute
+ 'let t = (a == 2) && (mul(&a, 10) == 20);' + //
+ 'return a;',
+ _result: 20,
+ },
+ {
+ name: 'ShortCircuit_Or_LhsOnly',
+ _body:
+ // rhs should not execute
+ 'let t = (a == 2) || (mul(&a, 10) == 20);' + //
+ 'let r = (a == 2);' +
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'ShortCircuit_Or_LhsAndRhs',
+ _body:
+ // rhs should execute
+ 'let t = (a != 2) || (mul(&a, 10) == 20);' + //
+ 'let r = (a == 20);' +
+ 'return i32(r);',
+ _result: 1,
+ },
+ {
+ name: 'NoShortCircuit_And',
+ _body:
+ // rhs should execute
+ 'let t = (a != 2) & (mul(&a, 10) == 20);' + //
+ 'return a;',
+ _result: 20,
+ },
+ {
+ name: 'NoShortCircuit_Or',
+ _body:
+ // rhs should execute
+ 'let t = (a == 2) | (mul(&a, 10) == 20);' + //
+ 'return a;',
+ _result: 20,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('binary_mixed')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#logical-expr')
+ .desc('Tests order of evaluation of both arithmetic and logical binary expressions.')
+ .paramsSimple([
+ {
+ name: 'ArithAndLogical',
+ _body: 'return mul(&a, 10) - i32(mul(&a, 10) == 200 && mul(&a, 10) == 2000);',
+ _result: 20 - 1,
+ },
+ {
+ name: 'LogicalAndArith',
+ _body: 'return i32(mul(&a, 10) == 20 && mul(&a, 10) == 200) - mul(&a, 10);',
+ _result: 1 - 2000,
+ },
+ {
+ name: 'ArithAndLogical_ShortCircuit',
+ _body: 'return mul(&a, 10) - i32(mul(&a, 10) != 200 && mul(&a, 10) == 2000);',
+ _result: 20 - 0,
+ },
+ {
+ name: 'LogicalAndArith_ShortCircuit',
+ _body: 'return i32(mul(&a, 10) != 20 && mul(&a, 10) == 200) - mul(&a, 10);',
+ _result: 0 - 200,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('call')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls')
+ .desc('Tests order of evaluation of call expressions.')
+ .paramsSimple([
+ {
+ name: 'OneSE', //
+ _body: 'return sub_mul3(mul(&a, 2), 2, a, 3, 3, 4);',
+ _result: 4 * 2 - 4 * 3 - 3 * 4,
+ },
+ {
+ name: 'AllSE',
+ _body: 'return sub_mul3(mul(&a, 2), 2, mul(&a, 2), 3, mul(&a, 2), 4);',
+ _result: 4 * 2 - 8 * 3 - 16 * 4,
+ },
+ {
+ name: 'MiddleNotSE',
+ _body: 'return sub_mul3(mul(&a, 2), 2, a, 3, mul(&a, 2), 4);',
+ _result: 4 * 2 - 4 * 3 - 8 * 4,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('index_accessor')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#array-access-expr')
+ .desc('Tests order of evaluation of index accessor expressions.')
+ .paramsSimple([
+ {
+ name: 'LeftSE', //
+ _body: 'return arr2D[mul(&a, 2)][a];',
+ _result: 4 * 10 + 4,
+ },
+ {
+ name: 'RightSE', //
+ _body: 'return arr2D[a][mul(&a, 2)];',
+ _result: 2 * 10 + 4,
+ },
+ {
+ name: 'BothSE',
+ _body: 'return arr2D[mul(&a, 2)][mul(&a, 2)];',
+ _result: 4 * 10 + 8,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('assignment')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#assignment')
+ .desc('Tests order of evaluation of assignment statements.')
+ .paramsSimple([
+ {
+ name: 'ToArray1D',
+ _body:
+ 'arr1D_zero[mul(&a, 2)] = mul(&a, 2);' + //
+ 'return arr1D_zero[8];',
+ _result: 4,
+ },
+ {
+ name: 'ToArray2D',
+ _body:
+ 'arr2D_zero[mul(&a, 2)][mul(&a, 2)] = mul(&a, 2);' + //
+ 'return arr2D_zero[8][16];',
+ _result: 4,
+ },
+ {
+ name: 'ToArrayFromArray',
+ _body:
+ 'arr2D_zero[4][8] = 123;' +
+ 'arr1D_zero[mul(&a, 2)] = arr2D_zero[mul(&a, 2)][mul(&a, 2)];' +
+ 'return arr1D_zero[16];',
+ _result: 123,
+ },
+ {
+ name: 'ToArrayIndexedByArrayIndexedBySE',
+ _body:
+ 'var arr1 = arr1D_zero;' +
+ 'var arr2 = arr1D_zero;' +
+ 'arr2[8] = 3;' +
+ 'arr1[arr2[mul(&a, 2)]] = mul(&a, 2);' +
+ 'return arr1[3];',
+ _result: 4,
+ },
+ {
+ name: 'ToVec_BothSE',
+ _body:
+ 'a = 0;' +
+ 'vec4_zero[add(&a, 1)] = add(&a, 1);' + //
+ 'return vec4_zero[2];',
+ _result: 1,
+ },
+ {
+ name: 'ToVec_LeftSE',
+ _body:
+ 'vec4_zero[add(&a, 1)] = a;' + //
+ 'return vec4_zero[3];',
+ _result: 2,
+ },
+ {
+ name: 'ToVec_RightSE',
+ _body:
+ 'vec4_zero[a] = add(&a, 1);' + //
+ 'return vec4_zero[3];',
+ _result: 3,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('type_constructor')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#type-constructor-expr')
+ .desc('Tests order of evaluation of type constructor expressions.')
+ .paramsSimple([
+ {
+ name: 'Struct',
+ _body:
+ 'let r = S(mul(&a, 2), mul(&a, 2), mul(&a, 2));' + //
+ 'return sub_mul3(r.x, 2, r.y, 3, r.z, 4);',
+ _result: 4 * 2 - 8 * 3 - 16 * 4,
+ },
+ {
+ name: 'Array1D',
+ _body:
+ 'let r = array<i32, 3>(mul(&a, 2), mul(&a, 2), mul(&a, 2));' + //
+ 'return sub_mul3(r[0], 2, r[1], 3, r[2], 4);',
+ _result: 4 * 2 - 8 * 3 - 16 * 4,
+ },
+ {
+ name: 'Array2D',
+ _body:
+ 'let r = array<array<i32, 2>, 2>(array<i32, 2>(mul(&a, 2), mul(&a, 2)), array<i32, 2>(mul(&a, 2), mul(&a, 2)));' +
+ 'return sub_mul4(r[0][0], 2, r[0][1], 3, r[1][0], 4, r[1][1], 5);',
+ _result: 4 * 2 - 8 * 3 - 16 * 4 - 32 * 5,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+g.test('member_accessor')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#struct-access-expr')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#vector-access-expr')
+ .desc('Tests order of evaluation of member accessor expressions.')
+ .paramsSimple([
+ {
+ name: 'Vec',
+ _body: 'return vec3(mul(&a, 2)).x - vec3(mul(&a, 3)).x;',
+ _result: 4 - 12,
+ },
+ {
+ name: 'Struct',
+ _body: 'return make_S(mul(&a, 2)).x - make_S(mul(&a, 3)).x;',
+ _result: 4 - 12,
+ },
+ ])
+ .fn(t => run(t, t.params._body, t.params._result));
+
+function run(t, body, result) {
+ // WGSL source
+ const source =
+ common_source +
+ `
+fn test_body() -> i32 {
+ ${body}
+}
+
+@group(0) @binding(0) var<storage, read_write> output : i32;
+
+@compute @workgroup_size(1)
+fn main() {
+ output = test_body();
+}
+`;
+
+ // Construct a buffer to hold the results of the expression tests
+ const outputBufferSize = 4; // result : i32
+ const outputBuffer = t.device.createBuffer({
+ size: outputBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ const module = t.device.createShaderModule({ code: source });
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: { module, entryPoint: 'main' },
+ });
+
+ const group = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: outputBuffer } }],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, group);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+
+ t.queue.submit([encoder.finish()]);
+
+ const checkExpectation = outputData => {
+ const output = TypeI32.read(outputData, 0);
+ const got = output.value;
+ const expected = result;
+ if (got !== expected) {
+ return new Error(`returned: ${got}, expected: ${expected}`);
+ }
+ return undefined;
+ };
+
+ t.expectGPUBufferValuesPassCheck(outputBuffer, checkExpectation, {
+ type: Uint8Array,
+ typedLength: outputBufferSize,
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js
new file mode 100644
index 0000000000..d35889abfc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/binary.js
@@ -0,0 +1,9 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /* @returns an ExpressionBuilder that evaluates a binary operation */
+export function binary(op) {
+ return values => {
+ const values_str = values.map(v => `(${v})`);
+ return `(${values_str.join(op)})`;
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js
new file mode 100644
index 0000000000..332885554d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bitwise.spec.js
@@ -0,0 +1,224 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the bitwise binary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { i32, scalarType, u32 } from '../../../../util/conversion.js';
+import { allInputSources, run } from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('bitwise_or')
+ .specURL('https://www.w3.org/TR/WGSL/#bit-expr')
+ .desc(
+ `
+e1 | e2: T
+T is i32, u32, vecN<i32>, or vecN<u32>
+
+Bitwise-or. Component-wise when T is a vector.
+`
+ )
+ .params(u =>
+ u
+ .combine('type', ['i32', 'u32'])
+ .combine('inputSource', allInputSources)
+ .combine('vectorize', [undefined, 2, 3, 4])
+ )
+ .fn(async t => {
+ const type = scalarType(t.params.type);
+ const V = t.params.type === 'i32' ? i32 : u32;
+ const cases = [
+ // Static patterns
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b01010010001001010010001001010010), V(0b10100100010010100100010010100100)],
+ expected: V(0b11110110011011110110011011110110),
+ },
+ ];
+
+ // Permute all combinations of a single bit being set for the LHS and RHS
+ for (let i = 0; i < 32; i++) {
+ const lhs = 1 << i;
+ for (let j = 0; j < 32; j++) {
+ const rhs = 1 << j;
+ cases.push({
+ input: [V(lhs), V(rhs)],
+ expected: V(lhs | rhs),
+ });
+ }
+ }
+ await run(t, binary('|'), [type, type], type, t.params, cases);
+ });
+
+g.test('bitwise_and')
+ .specURL('https://www.w3.org/TR/WGSL/#bit-expr')
+ .desc(
+ `
+e1 & e2: T
+T is i32, u32, vecN<i32>, or vecN<u32>
+
+Bitwise-and. Component-wise when T is a vector.
+`
+ )
+ .params(u =>
+ u
+ .combine('type', ['i32', 'u32'])
+ .combine('inputSource', allInputSources)
+ .combine('vectorize', [undefined, 2, 3, 4])
+ )
+ .fn(async t => {
+ const type = scalarType(t.params.type);
+ const V = t.params.type === 'i32' ? i32 : u32;
+ const cases = [
+ // Static patterns
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b10100100010010100100010010100100), V(0b11111111111111111111111111111111)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b10100100010010100100010010100100)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b01010010001001010010001001010010), V(0b01011011101101011011101101011011)],
+ expected: V(0b01010010001001010010001001010010),
+ },
+ ];
+
+ // Permute all combinations of a single bit being set for the LHS and all but one bit set for the RHS
+ for (let i = 0; i < 32; i++) {
+ const lhs = 1 << i;
+ for (let j = 0; j < 32; j++) {
+ const rhs = 0xffffffff ^ (1 << j);
+ cases.push({
+ input: [V(lhs), V(rhs)],
+ expected: V(lhs & rhs),
+ });
+ }
+ }
+ await run(t, binary('&'), [type, type], type, t.params, cases);
+ });
+
+g.test('bitwise_exclusive_or')
+ .specURL('https://www.w3.org/TR/WGSL/#bit-expr')
+ .desc(
+ `
+e1 ^ e2: T
+T is i32, u32, vecN<i32>, or vecN<u32>
+
+Bitwise-exclusive-or. Component-wise when T is a vector.
+`
+ )
+ .params(u =>
+ u
+ .combine('type', ['i32', 'u32'])
+ .combine('inputSource', allInputSources)
+ .combine('vectorize', [undefined, 2, 3, 4])
+ )
+ .fn(async t => {
+ const type = scalarType(t.params.type);
+ const V = t.params.type === 'i32' ? i32 : u32;
+ const cases = [
+ // Static patterns
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b00000000000000000000000000000000)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b00000000000000000000000000000000)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b11111111111111111111111111111111)],
+ expected: V(0b11111111111111111111111111111111),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b11111111111111111111111111111111)],
+ expected: V(0b00000000000000000000000000000000),
+ },
+ {
+ input: [V(0b10100100010010100100010010100100), V(0b00000000000000000000000000000000)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b10100100010010100100010010100100), V(0b11111111111111111111111111111111)],
+ expected: V(0b01011011101101011011101101011011),
+ },
+ {
+ input: [V(0b00000000000000000000000000000000), V(0b10100100010010100100010010100100)],
+ expected: V(0b10100100010010100100010010100100),
+ },
+ {
+ input: [V(0b11111111111111111111111111111111), V(0b10100100010010100100010010100100)],
+ expected: V(0b01011011101101011011101101011011),
+ },
+ {
+ input: [V(0b01010010001001010010001001010010), V(0b01011011101101011011101101011011)],
+ expected: V(0b00001001100100001001100100001001),
+ },
+ ];
+
+ // Permute all combinations of a single bit being set for the LHS and all but one bit set for the RHS
+ for (let i = 0; i < 32; i++) {
+ const lhs = 1 << i;
+ for (let j = 0; j < 32; j++) {
+ const rhs = 0xffffffff ^ (1 << j);
+ cases.push({
+ input: [V(lhs), V(rhs)],
+ expected: V(lhs ^ rhs),
+ });
+ }
+ }
+ await run(t, binary('^'), [type, type], type, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js
new file mode 100644
index 0000000000..25409d9b2d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/bool_logical.spec.js
@@ -0,0 +1,136 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the boolean binary logical expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { bool, TypeBool } from '../../../../util/conversion.js';
+import { allInputSources, run } from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// Short circuiting vs no short circuiting is not tested here, it is covered in
+// src/webgpu/shader/execution/evaluation_order.spec.ts
+
+g.test('and')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 & e2
+Logical "and". Component-wise when T is a vector. Evaluates both e1 and e2.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(false) },
+ { input: [bool(true), bool(false)], expected: bool(false) },
+ { input: [bool(false), bool(true)], expected: bool(false) },
+ { input: [bool(true), bool(true)], expected: bool(true) },
+ ];
+
+ await run(t, binary('&'), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
+
+g.test('and_short_circuit')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 && e2
+short_circuiting "and". Yields true if both e1 and e2 are true; evaluates e2 only if e1 is true.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(false) },
+ { input: [bool(true), bool(false)], expected: bool(false) },
+ { input: [bool(false), bool(true)], expected: bool(false) },
+ { input: [bool(true), bool(true)], expected: bool(true) },
+ ];
+
+ await run(t, binary('&&'), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
+
+g.test('or')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 | e2
+Logical "or". Component-wise when T is a vector. Evaluates both e1 and e2.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(false) },
+ { input: [bool(true), bool(false)], expected: bool(true) },
+ { input: [bool(false), bool(true)], expected: bool(true) },
+ { input: [bool(true), bool(true)], expected: bool(true) },
+ ];
+
+ await run(t, binary('|'), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
+
+g.test('or_short_circuit')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 || e2
+short_circuiting "and". Yields true if both e1 and e2 are true; evaluates e2 only if e1 is true.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(false) },
+ { input: [bool(true), bool(false)], expected: bool(true) },
+ { input: [bool(false), bool(true)], expected: bool(true) },
+ { input: [bool(true), bool(true)], expected: bool(true) },
+ ];
+
+ await run(t, binary('||'), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
+
+g.test('equals')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 == e2
+Equality. Component-wise when T is a vector.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(true) },
+ { input: [bool(true), bool(false)], expected: bool(false) },
+ { input: [bool(false), bool(true)], expected: bool(false) },
+ { input: [bool(true), bool(true)], expected: bool(true) },
+ ];
+
+ await run(t, binary('=='), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
+
+g.test('not_equals')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: e1 != e2
+Equality. Component-wise when T is a vector.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = [
+ { input: [bool(false), bool(false)], expected: bool(false) },
+ { input: [bool(true), bool(false)], expected: bool(true) },
+ { input: [bool(false), bool(true)], expected: bool(true) },
+ { input: [bool(true), bool(true)], expected: bool(false) },
+ ];
+
+ await run(t, binary('!='), [TypeBool, TypeBool], TypeBool, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_arithmetic.spec.js
new file mode 100644
index 0000000000..cd487caed6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_arithmetic.spec.js
@@ -0,0 +1,190 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the f32 arithmetic binary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { TypeF32 } from '../../../../util/conversion.js';
+import {
+ additionInterval,
+ divisionInterval,
+ multiplicationInterval,
+ remainderInterval,
+ subtractionInterval,
+} from '../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import { allInputSources, generateBinaryToF32IntervalCases, run } from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('binary/f32_arithmetic', {
+ addition_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ additionInterval
+ );
+ },
+ addition_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ additionInterval
+ );
+ },
+ subtraction_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ subtractionInterval
+ );
+ },
+ subtraction_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ subtractionInterval
+ );
+ },
+ multiplication_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ multiplicationInterval
+ );
+ },
+ multiplication_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ multiplicationInterval
+ );
+ },
+ division_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ divisionInterval
+ );
+ },
+ division_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ divisionInterval
+ );
+ },
+ remainder_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ remainderInterval
+ );
+ },
+ remainder_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ remainderInterval
+ );
+ },
+});
+
+g.test('addition')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x + y
+Accuracy: Correctly rounded
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'addition_const' : 'addition_non_const'
+ );
+
+ await run(t, binary('+'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('subtraction')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x - y
+Accuracy: Correctly rounded
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'subtraction_const' : 'subtraction_non_const'
+ );
+
+ await run(t, binary('-'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('multiplication')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x * y
+Accuracy: Correctly rounded
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'multiplication_const' : 'multiplication_non_const'
+ );
+
+ await run(t, binary('*'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('division')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x / y
+Accuracy: 2.5 ULP for |y| in the range [2^-126, 2^126]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'division_const' : 'division_non_const'
+ );
+
+ await run(t, binary('/'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('remainder')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x % y
+Accuracy: Derived from x - y * trunc(x/y)
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const'
+ );
+
+ await run(t, binary('%'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_logical.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_logical.spec.js
new file mode 100644
index 0000000000..29f7f490b7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/f32_logical.spec.js
@@ -0,0 +1,251 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the f32 logical binary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { anyOf } from '../../../../util/compare.js';
+import { bool, f32, TypeBool, TypeF32 } from '../../../../util/conversion.js';
+import { flushSubnormalScalarF32, vectorF32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import { allInputSources, run } from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+/**
+ * @returns a test case for the provided left hand & right hand values and truth function.
+ * Handles quantization and subnormals.
+ */
+function makeCase(lhs, rhs, truthFunc) {
+ const f32_lhs = f32(lhs);
+ const f32_rhs = f32(rhs);
+ const lhs_options = new Set([f32_lhs, flushSubnormalScalarF32(f32_lhs)]);
+ const rhs_options = new Set([f32_rhs, flushSubnormalScalarF32(f32_rhs)]);
+ const expected = [];
+ lhs_options.forEach(l => {
+ rhs_options.forEach(r => {
+ const result = bool(truthFunc(l, r));
+ if (!expected.includes(result)) {
+ expected.push(result);
+ }
+ });
+ });
+
+ return { input: [f32_lhs, f32_rhs], expected: anyOf(...expected) };
+}
+
+export const d = makeCaseCache('binary/f32_logical', {
+ equals_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value === rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ equals_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value === rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ not_equals_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value !== rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ not_equals_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value !== rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ less_than_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value < rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ less_than_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value < rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ less_equals_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value <= rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ less_equals_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value <= rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ greater_than_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value > rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ greater_than_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value > rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ greater_equals_non_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value >= rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+ greater_equals_const: () => {
+ const truthFunc = (lhs, rhs) => {
+ return lhs.value >= rhs.value;
+ };
+
+ return vectorF32Range(2).map(v => {
+ return makeCase(v[0], v[1], truthFunc);
+ });
+ },
+});
+
+g.test('equals')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x == y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'equals_const' : 'equals_non_const'
+ );
+
+ await run(t, binary('=='), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
+
+g.test('not_equals')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x != y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'not_equals_const' : 'not_equals_non_const'
+ );
+
+ await run(t, binary('!='), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
+
+g.test('less_than')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x < y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'less_than_const' : 'less_than_non_const'
+ );
+
+ await run(t, binary('<'), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
+
+g.test('less_equals')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x <= y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'less_equals_const' : 'less_equals_non_const'
+ );
+
+ await run(t, binary('<='), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
+
+g.test('greater_than')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x > y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'greater_than_const' : 'greater_than_non_const'
+ );
+
+ await run(t, binary('>'), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
+
+g.test('greater_equals')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x >= y
+Accuracy: Correct result
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'greater_equals_const' : 'greater_equals_non_const'
+ );
+
+ await run(t, binary('>='), [TypeF32, TypeF32], TypeBool, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js
new file mode 100644
index 0000000000..1775555158
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/i32_arithmetic.spec.js
@@ -0,0 +1,149 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the i32 arithmetic binary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { kValue } from '../../../../util/constants.js';
+import { TypeI32 } from '../../../../util/conversion.js';
+import { fullI32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import { allInputSources, generateBinaryToI32Cases, run } from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('binary/i32_arithmetic', {
+ addition: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ return x + y;
+ });
+ },
+ subtraction: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ return x - y;
+ });
+ },
+ multiplication: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ division_non_const: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ if (y === 0) {
+ return x;
+ }
+ if (x === kValue.i32.negative.min && y === -1) {
+ return x;
+ }
+ return x / y;
+ });
+ },
+ division_const: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ if (y === 0) {
+ return undefined;
+ }
+ if (x === kValue.i32.negative.min && y === -1) {
+ return undefined;
+ }
+ return x / y;
+ });
+ },
+ remainder_non_const: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ if (y === 0) {
+ return 0;
+ }
+ if (x === kValue.i32.negative.min && y === -1) {
+ return 0;
+ }
+ return x % y;
+ });
+ },
+ remainder_const: () => {
+ return generateBinaryToI32Cases(fullI32Range(), fullI32Range(), (x, y) => {
+ if (y === 0) {
+ return undefined;
+ }
+ if (x === kValue.i32.negative.min && y === -1) {
+ return undefined;
+ }
+ return x % y;
+ });
+ },
+});
+
+g.test('addition')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x + y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('addition');
+ await run(t, binary('+'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('subtraction')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x - y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('subtraction');
+ await run(t, binary('-'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('multiplication')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x * y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('multiplication');
+ await run(t, binary('*'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('division')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x / y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'division_const' : 'division_non_const'
+ );
+
+ await run(t, binary('/'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('remainder')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: x % y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const'
+ );
+
+ await run(t, binary('%'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js
new file mode 100644
index 0000000000..4e7bfd84a2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/binary/u32_arithmetic.spec.js
@@ -0,0 +1,202 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the u32 arithmetic binary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { TypeU32, TypeVec } from '../../../../util/conversion.js';
+import { fullU32Range, sparseU32Range, vectorU32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import {
+ allInputSources,
+ generateBinaryToU32Cases,
+ generateU32VectorBinaryToVectorCases,
+ generateVectorU32BinaryToVectorCases,
+ run,
+} from '../expression.js';
+
+import { binary } from './binary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('binary/u32_arithmetic', {
+ addition: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ return x + y;
+ });
+ },
+ subtraction: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ return x - y;
+ });
+ },
+ multiplication: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ division_non_const: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ if (y === 0) {
+ return x;
+ }
+ return x / y;
+ });
+ },
+ division_const: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ if (y === 0) {
+ return undefined;
+ }
+ return x / y;
+ });
+ },
+ remainder_non_const: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ if (y === 0) {
+ return 0;
+ }
+ return x % y;
+ });
+ },
+ remainder_const: () => {
+ return generateBinaryToU32Cases(fullU32Range(), fullU32Range(), (x, y) => {
+ if (y === 0) {
+ return undefined;
+ }
+ return x % y;
+ });
+ },
+ multiplication_scalar_vector2: () => {
+ return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(2), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ multiplication_scalar_vector3: () => {
+ return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(3), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ multiplication_scalar_vector4: () => {
+ return generateU32VectorBinaryToVectorCases(sparseU32Range(), vectorU32Range(4), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ multiplication_vector2_scalar: () => {
+ return generateVectorU32BinaryToVectorCases(vectorU32Range(2), sparseU32Range(), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ multiplication_vector3_scalar: () => {
+ return generateVectorU32BinaryToVectorCases(vectorU32Range(3), sparseU32Range(), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+ multiplication_vector4_scalar: () => {
+ return generateVectorU32BinaryToVectorCases(vectorU32Range(4), sparseU32Range(), (x, y) => {
+ return Math.imul(x, y);
+ });
+ },
+});
+
+g.test('addition')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x + y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('addition');
+ await run(t, binary('+'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('subtraction')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x - y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('subtraction');
+ await run(t, binary('-'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('multiplication')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x * y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('multiplication');
+ await run(t, binary('*'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('division')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x / y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'division_const' : 'division_non_const'
+ );
+
+ await run(t, binary('/'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('remainder')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x % y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'remainder_const' : 'remainder_non_const'
+ );
+
+ await run(t, binary('%'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('multiplication_scalar_vector')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x * y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize_rhs', [2, 3, 4]))
+ .fn(async t => {
+ const vec_size = t.params.vectorize_rhs;
+ const vec_type = TypeVec(vec_size, TypeU32);
+ const cases = await d.get(`multiplication_scalar_vector${vec_size}`);
+ await run(t, binary('*'), [TypeU32, vec_type], vec_type, t.params, cases);
+ });
+
+g.test('multiplication_vector_scalar')
+ .specURL('https://www.w3.org/TR/WGSL/#arithmetic-expr')
+ .desc(
+ `
+Expression: x * y
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize_lhs', [2, 3, 4]))
+ .fn(async t => {
+ const vec_size = t.params.vectorize_lhs;
+ const vec_type = TypeVec(vec_size, TypeU32);
+ const cases = await d.get(`multiplication_vector${vec_size}_scalar`);
+ await run(t, binary('*'), [vec_type, TypeU32], vec_type, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js
new file mode 100644
index 0000000000..24525e233d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/abs.spec.js
@@ -0,0 +1,156 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'abs' builtin function
+
+S is AbstractInt, i32, or u32
+T is S or vecN<S>
+@const fn abs(e: T ) -> T
+The absolute value of e. Component-wise when T is a vector. If e is a signed
+integral scalar type and evaluates to the largest negative value, then the
+result is e. If e is an unsigned integral type, then the result is e.
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn abs(e: T ) -> T
+Returns the absolute value of e (e.g. e with a positive sign bit).
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kBit } from '../../../../../util/constants.js';
+import { i32Bits, TypeF32, TypeI32, TypeU32, u32Bits } from '../../../../../util/conversion.js';
+import { absInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('abs', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', absInterval);
+ },
+});
+
+g.test('abstract_int')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`abstract int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`unsigned int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ await run(t, builtin('abs'), [TypeU32], TypeU32, t.params, [
+ // Min and Max u32
+ { input: u32Bits(kBit.u32.min), expected: u32Bits(kBit.u32.min) },
+ { input: u32Bits(kBit.u32.max), expected: u32Bits(kBit.u32.max) },
+ // Powers of 2: -2^i: 0 =< i =< 31
+ { input: u32Bits(kBit.powTwo.to0), expected: u32Bits(kBit.powTwo.to0) },
+ { input: u32Bits(kBit.powTwo.to1), expected: u32Bits(kBit.powTwo.to1) },
+ { input: u32Bits(kBit.powTwo.to2), expected: u32Bits(kBit.powTwo.to2) },
+ { input: u32Bits(kBit.powTwo.to3), expected: u32Bits(kBit.powTwo.to3) },
+ { input: u32Bits(kBit.powTwo.to4), expected: u32Bits(kBit.powTwo.to4) },
+ { input: u32Bits(kBit.powTwo.to5), expected: u32Bits(kBit.powTwo.to5) },
+ { input: u32Bits(kBit.powTwo.to6), expected: u32Bits(kBit.powTwo.to6) },
+ { input: u32Bits(kBit.powTwo.to7), expected: u32Bits(kBit.powTwo.to7) },
+ { input: u32Bits(kBit.powTwo.to8), expected: u32Bits(kBit.powTwo.to8) },
+ { input: u32Bits(kBit.powTwo.to9), expected: u32Bits(kBit.powTwo.to9) },
+ { input: u32Bits(kBit.powTwo.to10), expected: u32Bits(kBit.powTwo.to10) },
+ { input: u32Bits(kBit.powTwo.to11), expected: u32Bits(kBit.powTwo.to11) },
+ { input: u32Bits(kBit.powTwo.to12), expected: u32Bits(kBit.powTwo.to12) },
+ { input: u32Bits(kBit.powTwo.to13), expected: u32Bits(kBit.powTwo.to13) },
+ { input: u32Bits(kBit.powTwo.to14), expected: u32Bits(kBit.powTwo.to14) },
+ { input: u32Bits(kBit.powTwo.to15), expected: u32Bits(kBit.powTwo.to15) },
+ { input: u32Bits(kBit.powTwo.to16), expected: u32Bits(kBit.powTwo.to16) },
+ { input: u32Bits(kBit.powTwo.to17), expected: u32Bits(kBit.powTwo.to17) },
+ { input: u32Bits(kBit.powTwo.to18), expected: u32Bits(kBit.powTwo.to18) },
+ { input: u32Bits(kBit.powTwo.to19), expected: u32Bits(kBit.powTwo.to19) },
+ { input: u32Bits(kBit.powTwo.to20), expected: u32Bits(kBit.powTwo.to20) },
+ { input: u32Bits(kBit.powTwo.to21), expected: u32Bits(kBit.powTwo.to21) },
+ { input: u32Bits(kBit.powTwo.to22), expected: u32Bits(kBit.powTwo.to22) },
+ { input: u32Bits(kBit.powTwo.to23), expected: u32Bits(kBit.powTwo.to23) },
+ { input: u32Bits(kBit.powTwo.to24), expected: u32Bits(kBit.powTwo.to24) },
+ { input: u32Bits(kBit.powTwo.to25), expected: u32Bits(kBit.powTwo.to25) },
+ { input: u32Bits(kBit.powTwo.to26), expected: u32Bits(kBit.powTwo.to26) },
+ { input: u32Bits(kBit.powTwo.to27), expected: u32Bits(kBit.powTwo.to27) },
+ { input: u32Bits(kBit.powTwo.to28), expected: u32Bits(kBit.powTwo.to28) },
+ { input: u32Bits(kBit.powTwo.to29), expected: u32Bits(kBit.powTwo.to29) },
+ { input: u32Bits(kBit.powTwo.to30), expected: u32Bits(kBit.powTwo.to30) },
+ { input: u32Bits(kBit.powTwo.to31), expected: u32Bits(kBit.powTwo.to31) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`signed int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ await run(t, builtin('abs'), [TypeI32], TypeI32, t.params, [
+ // Min and max i32
+ // If e evaluates to the largest negative value, then the result is e.
+ { input: i32Bits(kBit.i32.negative.min), expected: i32Bits(kBit.i32.negative.min) },
+ { input: i32Bits(kBit.i32.negative.max), expected: i32Bits(kBit.i32.positive.min) },
+ { input: i32Bits(kBit.i32.positive.max), expected: i32Bits(kBit.i32.positive.max) },
+ { input: i32Bits(kBit.i32.positive.min), expected: i32Bits(kBit.i32.positive.min) },
+ // input: -1 * pow(2, n), n = {-31, ..., 0 }, expected: pow(2, n), n = {-31, ..., 0}]
+ { input: i32Bits(kBit.negPowTwo.to0), expected: i32Bits(kBit.powTwo.to0) },
+ { input: i32Bits(kBit.negPowTwo.to1), expected: i32Bits(kBit.powTwo.to1) },
+ { input: i32Bits(kBit.negPowTwo.to2), expected: i32Bits(kBit.powTwo.to2) },
+ { input: i32Bits(kBit.negPowTwo.to3), expected: i32Bits(kBit.powTwo.to3) },
+ { input: i32Bits(kBit.negPowTwo.to4), expected: i32Bits(kBit.powTwo.to4) },
+ { input: i32Bits(kBit.negPowTwo.to5), expected: i32Bits(kBit.powTwo.to5) },
+ { input: i32Bits(kBit.negPowTwo.to6), expected: i32Bits(kBit.powTwo.to6) },
+ { input: i32Bits(kBit.negPowTwo.to7), expected: i32Bits(kBit.powTwo.to7) },
+ { input: i32Bits(kBit.negPowTwo.to8), expected: i32Bits(kBit.powTwo.to8) },
+ { input: i32Bits(kBit.negPowTwo.to9), expected: i32Bits(kBit.powTwo.to9) },
+ { input: i32Bits(kBit.negPowTwo.to10), expected: i32Bits(kBit.powTwo.to10) },
+ { input: i32Bits(kBit.negPowTwo.to11), expected: i32Bits(kBit.powTwo.to11) },
+ { input: i32Bits(kBit.negPowTwo.to12), expected: i32Bits(kBit.powTwo.to12) },
+ { input: i32Bits(kBit.negPowTwo.to13), expected: i32Bits(kBit.powTwo.to13) },
+ { input: i32Bits(kBit.negPowTwo.to14), expected: i32Bits(kBit.powTwo.to14) },
+ { input: i32Bits(kBit.negPowTwo.to15), expected: i32Bits(kBit.powTwo.to15) },
+ { input: i32Bits(kBit.negPowTwo.to16), expected: i32Bits(kBit.powTwo.to16) },
+ { input: i32Bits(kBit.negPowTwo.to17), expected: i32Bits(kBit.powTwo.to17) },
+ { input: i32Bits(kBit.negPowTwo.to18), expected: i32Bits(kBit.powTwo.to18) },
+ { input: i32Bits(kBit.negPowTwo.to19), expected: i32Bits(kBit.powTwo.to19) },
+ { input: i32Bits(kBit.negPowTwo.to20), expected: i32Bits(kBit.powTwo.to20) },
+ { input: i32Bits(kBit.negPowTwo.to21), expected: i32Bits(kBit.powTwo.to21) },
+ { input: i32Bits(kBit.negPowTwo.to22), expected: i32Bits(kBit.powTwo.to22) },
+ { input: i32Bits(kBit.negPowTwo.to23), expected: i32Bits(kBit.powTwo.to23) },
+ { input: i32Bits(kBit.negPowTwo.to24), expected: i32Bits(kBit.powTwo.to24) },
+ { input: i32Bits(kBit.negPowTwo.to25), expected: i32Bits(kBit.powTwo.to25) },
+ { input: i32Bits(kBit.negPowTwo.to26), expected: i32Bits(kBit.powTwo.to26) },
+ { input: i32Bits(kBit.negPowTwo.to27), expected: i32Bits(kBit.powTwo.to27) },
+ { input: i32Bits(kBit.negPowTwo.to28), expected: i32Bits(kBit.powTwo.to28) },
+ { input: i32Bits(kBit.negPowTwo.to29), expected: i32Bits(kBit.powTwo.to29) },
+ { input: i32Bits(kBit.negPowTwo.to30), expected: i32Bits(kBit.powTwo.to30) },
+ { input: i32Bits(kBit.negPowTwo.to31), expected: i32Bits(kBit.powTwo.to31) },
+ ]);
+ });
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`float 32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('abs'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js
new file mode 100644
index 0000000000..fa3ab3db25
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acos.spec.js
@@ -0,0 +1,56 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'acos' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn acos(e: T ) -> T
+Returns the arc cosine of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { acosInterval } from '../../../../../util/f32_interval.js';
+import { linearRange, fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const inputs = [
+ ...linearRange(-1, 1, 100), // acos is defined on [-1, 1]
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('acos', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', acosInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', acosInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('acos'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js
new file mode 100644
index 0000000000..c3d2505488
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/acosh.spec.js
@@ -0,0 +1,60 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'acosh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn acosh(e: T ) -> T
+Returns the hyperbolic arc cosine of e. The result is 0 when e < 1.
+Computes the non-negative functional inverse of cosh.
+Component-wise when T is a vector.
+Note: The result is not mathematically meaningful when e < 1.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { acoshIntervals } from '../../../../../util/f32_interval.js';
+import { biasedRange, fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const inputs = [
+ ...biasedRange(1, 2, 100), // x near 1 can be problematic to implement
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('acosh', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', ...acoshIntervals);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', ...acoshIntervals);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('acosh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js
new file mode 100644
index 0000000000..cb8b32953f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/all.spec.js
@@ -0,0 +1,93 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'all' builtin function
+
+S is a bool
+T is S or vecN<S>
+@const fn all(e: T) -> bool
+Returns e if e is scalar.
+Returns true if each component of e is true if e is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import {
+ False,
+ True,
+ TypeBool,
+ TypeVec,
+ vec2,
+ vec3,
+ vec4,
+} from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('bool')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-builtin-functions')
+ .desc(`bool tests`)
+ .params(u =>
+ u
+ .combine('inputSource', allInputSources)
+ .combine('overload', ['scalar', 'vec2', 'vec3', 'vec4'])
+ )
+ .fn(async t => {
+ const overloads = {
+ scalar: {
+ type: TypeBool,
+ cases: [
+ { input: False, expected: False },
+ { input: True, expected: True },
+ ],
+ },
+ vec2: {
+ type: TypeVec(2, TypeBool),
+ cases: [
+ { input: vec2(False, False), expected: False },
+ { input: vec2(True, False), expected: False },
+ { input: vec2(False, True), expected: False },
+ { input: vec2(True, True), expected: True },
+ ],
+ },
+ vec3: {
+ type: TypeVec(3, TypeBool),
+ cases: [
+ { input: vec3(False, False, False), expected: False },
+ { input: vec3(True, False, False), expected: False },
+ { input: vec3(False, True, False), expected: False },
+ { input: vec3(True, True, False), expected: False },
+ { input: vec3(False, False, True), expected: False },
+ { input: vec3(True, False, True), expected: False },
+ { input: vec3(False, True, True), expected: False },
+ { input: vec3(True, True, True), expected: True },
+ ],
+ },
+ vec4: {
+ type: TypeVec(4, TypeBool),
+ cases: [
+ { input: vec4(False, False, False, False), expected: False },
+ { input: vec4(False, True, False, False), expected: False },
+ { input: vec4(False, False, True, False), expected: False },
+ { input: vec4(False, True, True, False), expected: False },
+ { input: vec4(False, False, False, True), expected: False },
+ { input: vec4(False, True, False, True), expected: False },
+ { input: vec4(False, False, True, True), expected: False },
+ { input: vec4(False, True, True, True), expected: False },
+ { input: vec4(True, False, False, False), expected: False },
+ { input: vec4(True, False, False, True), expected: False },
+ { input: vec4(True, False, True, False), expected: False },
+ { input: vec4(True, False, True, True), expected: False },
+ { input: vec4(True, True, False, False), expected: False },
+ { input: vec4(True, True, False, True), expected: False },
+ { input: vec4(True, True, True, False), expected: False },
+ { input: vec4(True, True, True, True), expected: True },
+ ],
+ },
+ };
+ const overload = overloads[t.params.overload];
+
+ await run(t, builtin('all'), [overload.type], TypeBool, t.params, overload.cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js
new file mode 100644
index 0000000000..9f5b4524f1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/any.spec.js
@@ -0,0 +1,93 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'any' builtin function
+
+S is a bool
+T is S or vecN<S>
+@const fn all(e) -> bool
+Returns e if e is scalar.
+Returns true if any component of e is true if e is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import {
+ False,
+ True,
+ TypeBool,
+ TypeVec,
+ vec2,
+ vec3,
+ vec4,
+} from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('bool')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-builtin-functions')
+ .desc(`bool tests`)
+ .params(u =>
+ u
+ .combine('inputSource', allInputSources)
+ .combine('overload', ['scalar', 'vec2', 'vec3', 'vec4'])
+ )
+ .fn(async t => {
+ const overloads = {
+ scalar: {
+ type: TypeBool,
+ cases: [
+ { input: False, expected: False },
+ { input: True, expected: True },
+ ],
+ },
+ vec2: {
+ type: TypeVec(2, TypeBool),
+ cases: [
+ { input: vec2(False, False), expected: False },
+ { input: vec2(True, False), expected: True },
+ { input: vec2(False, True), expected: True },
+ { input: vec2(True, True), expected: True },
+ ],
+ },
+ vec3: {
+ type: TypeVec(3, TypeBool),
+ cases: [
+ { input: vec3(False, False, False), expected: False },
+ { input: vec3(True, False, False), expected: True },
+ { input: vec3(False, True, False), expected: True },
+ { input: vec3(True, True, False), expected: True },
+ { input: vec3(False, False, True), expected: True },
+ { input: vec3(True, False, True), expected: True },
+ { input: vec3(False, True, True), expected: True },
+ { input: vec3(True, True, True), expected: True },
+ ],
+ },
+ vec4: {
+ type: TypeVec(4, TypeBool),
+ cases: [
+ { input: vec4(False, False, False, False), expected: False },
+ { input: vec4(False, True, False, False), expected: True },
+ { input: vec4(False, False, True, False), expected: True },
+ { input: vec4(False, True, True, False), expected: True },
+ { input: vec4(False, False, False, True), expected: True },
+ { input: vec4(False, True, False, True), expected: True },
+ { input: vec4(False, False, True, True), expected: True },
+ { input: vec4(False, True, True, True), expected: True },
+ { input: vec4(True, False, False, False), expected: True },
+ { input: vec4(True, False, False, True), expected: True },
+ { input: vec4(True, False, True, False), expected: True },
+ { input: vec4(True, False, True, True), expected: True },
+ { input: vec4(True, True, False, False), expected: True },
+ { input: vec4(True, True, False, True), expected: True },
+ { input: vec4(True, True, True, False), expected: True },
+ { input: vec4(True, True, True, True), expected: True },
+ ],
+ },
+ };
+ const overload = overloads[t.params.overload];
+
+ await run(t, builtin('any'), [overload.type], TypeBool, t.params, overload.cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/arrayLength.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/arrayLength.spec.js
new file mode 100644
index 0000000000..26567d9c42
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/arrayLength.spec.js
@@ -0,0 +1,17 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'arrayLength' builtin function
+
+fn arrayLength(e: ptr<storage,array<T>> ) -> u32
+Returns the number of elements in the runtime-sized array.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('array')
+ .specURL('https://www.w3.org/TR/WGSL/#array-builtin-functions')
+ .desc(`array length tests`)
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js
new file mode 100644
index 0000000000..d5866440e7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asin.spec.js
@@ -0,0 +1,56 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'asin' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn asin(e: T ) -> T
+Returns the arc sine of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { asinInterval } from '../../../../../util/f32_interval.js';
+import { linearRange, fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const inputs = [
+ ...linearRange(-1, 1, 100), // asin is defined on [-1, 1]
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('asin', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', asinInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', asinInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('asin'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js
new file mode 100644
index 0000000000..8b3cf59ab5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/asinh.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'sinh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn asinh(e: T ) -> T
+Returns the hyperbolic arc sine of e.
+Computes the functional inverse of sinh.
+Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { asinhInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('asinh', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', asinhInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float test`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('asinh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js
new file mode 100644
index 0000000000..390c2fb8a4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan.spec.js
@@ -0,0 +1,71 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'atan' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn atan(e: T ) -> T
+Returns the arc tangent of e. Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { atanInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const inputs = [
+ // Known values
+ -Math.sqrt(3),
+ -1,
+ -1 / Math.sqrt(3),
+ 0,
+ 1,
+ 1 / Math.sqrt(3),
+ Math.sqrt(3),
+
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('atan', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', atanInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', atanInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('atan'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js
new file mode 100644
index 0000000000..5205fe014d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atan2.spec.js
@@ -0,0 +1,67 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'atan2' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn atan2(e1: T ,e2: T ) -> T
+Returns the arc tangent of e1 over e2. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { atan2Interval } from '../../../../../util/f32_interval.js';
+import { linearRange, sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateBinaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('atan2', {
+ f32: () => {
+ // Using sparse, since there a N^2 cases being generated, but including extra values around 0, since that is where
+ // there is a discontinuity that implementations tend to behave badly at.
+ const numeric_range = [
+ ...sparseF32Range(),
+ ...linearRange(kValue.f32.negative.max, kValue.f32.positive.min, 10),
+ ];
+
+ return generateBinaryToF32IntervalCases(
+ numeric_range,
+ numeric_range,
+ 'unfiltered',
+ atan2Interval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('atan2'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js
new file mode 100644
index 0000000000..79f3dc6c59
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atanh.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'atanh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn atanh(e: T ) -> T
+Returns the hyperbolic arc tangent of e. The result is 0 when abs(e) ≥ 1.
+Computes the functional inverse of tanh.
+Component-wise when T is a vector.
+Note: The result is not mathematically meaningful when abs(e) >= 1.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { atanhInterval } from '../../../../../util/f32_interval.js';
+import { biasedRange, fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const inputs = [
+ ...biasedRange(kValue.f32.negative.less_than_one, -0.9, 20), // discontinuity at x = -1
+ -1,
+ ...biasedRange(kValue.f32.positive.less_than_one, 0.9, 20), // discontinuity at x = 1
+ 1,
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('atanh', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', atanhInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', atanhInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('atanh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAdd.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAdd.spec.js
new file mode 100644
index 0000000000..2d1d4589bc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAdd.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, add and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by adding with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('add')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicAdd(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAnd.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAnd.spec.js
new file mode 100644
index 0000000000..94ac8d300b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicAnd.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, and and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by anding with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('and')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicAnd(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicCompareExchangeWeak.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicCompareExchangeWeak.spec.js
new file mode 100644
index 0000000000..fb3d6b9fd7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicCompareExchangeWeak.spec.js
@@ -0,0 +1,48 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Performs the following steps atomically:
+ * Load the original value pointed to by atomic_ptr.
+ * Compare the original value to the value v using an equality operation.
+ * Store the value v only if the result of the equality comparison was true.
+
+Returns a two member structure, where the first member, old_value, is the original
+value of the atomic object and the second member, exchanged, is whether or not
+the comparison succeeded.
+
+Note: the equality comparison may spuriously fail on some implementations.
+That is, the second component of the result vector may be false even if the first
+component of the result vector equals cmp.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('exchange')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicCompareExchangeWeak(atomic_ptr: ptr<SC, atomic<T>, read_write>, cmp: T, v: T) -> __atomic_compare_exchange_result<T>
+
+struct __atomic_compare_exchange_result<T> {
+ old_value : T, // old value stored in the atomic
+ exchanged : bool, // true if the exchange was done
+}
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicExchange.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicExchange.spec.js
new file mode 100644
index 0000000000..e125d19321
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicExchange.spec.js
@@ -0,0 +1,32 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically stores the value v in the atomic object pointed to atomic_ptr and returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('exchange')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicExchange(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicLoad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicLoad.spec.js
new file mode 100644
index 0000000000..e9ca2ef65b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicLoad.spec.js
@@ -0,0 +1,33 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Returns the atomically loaded the value pointed to by atomic_ptr. It does not modify the object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-load')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('load')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-load')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicLoad(atomic_ptr: ptr<SC, atomic<T>, read_write>) -> T
+
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMax.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMax.spec.js
new file mode 100644
index 0000000000..816126caeb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMax.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, max and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by taking the max with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('max')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicMax(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMin.spec.js
new file mode 100644
index 0000000000..680e696539
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicMin.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, min and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by take the min with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('min')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicMin(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicOr.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicOr.spec.js
new file mode 100644
index 0000000000..14940ac5eb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicOr.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, or and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by or'ing with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('or')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicOr(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicStore.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicStore.spec.js
new file mode 100644
index 0000000000..04f84d37b7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicStore.spec.js
@@ -0,0 +1,32 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically stores the value v in the atomic object pointed to by atomic_ptr.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-store')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('store')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-store')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicStore(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T)
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicSub.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicSub.spec.js
new file mode 100644
index 0000000000..5834eff867
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicSub.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, subtract and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by subtracting with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('sub')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicSub(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicXor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicXor.spec.js
new file mode 100644
index 0000000000..7d8201d23b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/atomicXor.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Atomically read, xor and store value.
+
+ * Load the original value pointed to by atomic_ptr.
+ * Obtains a new value by xor'ing with the value v.
+ * Store the new value using atomic_ptr.
+
+Returns the original value stored in the atomic object.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+Atomic built-in functions must not be used in a vertex shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('xor')
+ .specURL('https://www.w3.org/TR/WGSL/#atomic-rmw')
+ .desc(
+ `
+SC is storage or workgroup
+T is i32 or u32
+
+fn atomicXor(atomic_ptr: ptr<SC, atomic<T>, read_write>, v: T) -> T
+`
+ )
+ .params(u => u.combine('SC', ['storage', 'uniform']).combine('T', ['i32', 'u32']))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js
new file mode 100644
index 0000000000..8b82212dfc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/builtin.js
@@ -0,0 +1,6 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /* @returns an ExpressionBuilder that calls the builtin with the given name */
+export function builtin(name) {
+ return values => `${name}(${values.join(', ')})`;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js
new file mode 100644
index 0000000000..8a2cf4a7ac
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ceil.spec.js
@@ -0,0 +1,68 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'ceil' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn ceil(e: T ) -> T
+Returns the ceiling of e. Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { ceilInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('ceil', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Small positive numbers
+ 0.1,
+ 0.9,
+ 1.0,
+ 1.1,
+ 1.9,
+ // Small negative numbers
+ -0.1,
+ -0.9,
+ -1.0,
+ -1.1,
+ -1.9,
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ ceilInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('ceil'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js
new file mode 100644
index 0000000000..3bb911291a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/clamp.spec.js
@@ -0,0 +1,160 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'clamp' builtin function
+
+S is AbstractInt, i32, or u32
+T is S or vecN<S>
+@const fn clamp(e: T , low: T, high: T) -> T
+Returns min(max(e,low),high). Component-wise when T is a vector.
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const clamp(e: T , low: T , high: T) -> T
+Returns either min(max(e,low),high), or the median of the three values e, low, high.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kBit } from '../../../../../util/constants.js';
+import {
+ i32,
+ i32Bits,
+ TypeF32,
+ TypeI32,
+ TypeU32,
+ u32,
+ u32Bits,
+} from '../../../../../util/conversion.js';
+import { clampIntervals } from '../../../../../util/f32_interval.js';
+import { sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateTernaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('clamp', {
+ u32: () => {
+ // This array must be strictly increasing, since that ordering determines
+ // the expected values.
+ const test_values = [
+ u32Bits(kBit.u32.min),
+ u32(1),
+ u32(2),
+ u32(0x70000000),
+ u32(0x80000000),
+ u32Bits(kBit.u32.max),
+ ];
+
+ return generateIntegerTestCases(test_values);
+ },
+ i32: () => {
+ // This array must be strictly increasing, since that ordering determines
+ // the expected values.
+ const test_values = [
+ i32Bits(kBit.i32.negative.min),
+ i32(-2),
+ i32(-1),
+ i32(0),
+ i32(1),
+ i32(2),
+ i32Bits(0x70000000),
+ i32Bits(kBit.i32.positive.max),
+ ];
+
+ return generateIntegerTestCases(test_values);
+ },
+ f32_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'f32-only',
+ ...clampIntervals
+ );
+ },
+ f32_non_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'unfiltered',
+ ...clampIntervals
+ );
+ },
+});
+
+/**
+ * Calculates clamp using the min-max formula.
+ * clamp(e, f, g) = min(max(e, f), g)
+ *
+ * Operates on indices of an ascending sorted array, instead of the actual
+ * values to avoid rounding issues.
+ *
+ * @returns the index of the clamped value
+ */
+function calculateMinMaxClamp(ei, fi, gi) {
+ return Math.min(Math.max(ei, fi), gi);
+}
+
+/** @returns a set of clamp test cases from an ascending list of integer values */
+function generateIntegerTestCases(test_values) {
+ const cases = new Array();
+ test_values.forEach((e, ei) => {
+ test_values.forEach((f, fi) => {
+ test_values.forEach((g, gi) => {
+ const expected_idx = calculateMinMaxClamp(ei, fi, gi);
+ const expected = test_values[expected_idx];
+ cases.push({ input: [e, f, g], expected });
+ });
+ });
+ });
+ return cases;
+}
+
+g.test('abstract_int')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`abstract int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('u32');
+ await run(t, builtin('clamp'), [TypeU32, TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('i32');
+ await run(t, builtin('clamp'), [TypeI32, TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('clamp'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js
new file mode 100644
index 0000000000..c867881c17
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cos.spec.js
@@ -0,0 +1,64 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'cos' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn cos(e: T ) -> T
+Returns the cosine of e. Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { cosInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('cos', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Well defined accuracy range
+ ...linearRange(-Math.PI, Math.PI, 1000),
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ cosInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('cos'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js
new file mode 100644
index 0000000000..6905f7360e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cosh.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'cosh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn cosh(e: T ) -> T
+Returns the hyperbolic cosine of e. Component-wise when T is a vector
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { coshInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('cosh', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'f32-only', coshInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', coshInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('cosh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js
new file mode 100644
index 0000000000..51a7a5ee1e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countLeadingZeros.spec.js
@@ -0,0 +1,247 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'countLeadingZeros' builtin function
+
+S is i32 or u32
+T is S or vecN<S>
+@const fn countLeadingZeros(e: T ) -> T
+The number of consecutive 0 bits starting from the most significant bit of e,
+when T is a scalar type.
+Component-wise when T is a vector.
+Also known as "clz" in some languages.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeU32, u32Bits, u32, TypeI32, i32Bits, i32 } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countLeadingZeros'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ { input: u32Bits(0b00000000000000000000000000000000), expected: u32(32) },
+
+ // One
+ { input: u32Bits(0b00000000000000000000000000000001), expected: u32(31) },
+
+ // 0's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000010), expected: u32(30) },
+ { input: u32Bits(0b00000000000000000000000000000100), expected: u32(29) },
+ { input: u32Bits(0b00000000000000000000000000001000), expected: u32(28) },
+ { input: u32Bits(0b00000000000000000000000000010000), expected: u32(27) },
+ { input: u32Bits(0b00000000000000000000000000100000), expected: u32(26) },
+ { input: u32Bits(0b00000000000000000000000001000000), expected: u32(25) },
+ { input: u32Bits(0b00000000000000000000000010000000), expected: u32(24) },
+ { input: u32Bits(0b00000000000000000000000100000000), expected: u32(23) },
+ { input: u32Bits(0b00000000000000000000001000000000), expected: u32(22) },
+ { input: u32Bits(0b00000000000000000000010000000000), expected: u32(21) },
+ { input: u32Bits(0b00000000000000000000100000000000), expected: u32(20) },
+ { input: u32Bits(0b00000000000000000001000000000000), expected: u32(19) },
+ { input: u32Bits(0b00000000000000000010000000000000), expected: u32(18) },
+ { input: u32Bits(0b00000000000000000100000000000000), expected: u32(17) },
+ { input: u32Bits(0b00000000000000001000000000000000), expected: u32(16) },
+ { input: u32Bits(0b00000000000000010000000000000000), expected: u32(15) },
+ { input: u32Bits(0b00000000000000100000000000000000), expected: u32(14) },
+ { input: u32Bits(0b00000000000001000000000000000000), expected: u32(13) },
+ { input: u32Bits(0b00000000000010000000000000000000), expected: u32(12) },
+ { input: u32Bits(0b00000000000100000000000000000000), expected: u32(11) },
+ { input: u32Bits(0b00000000001000000000000000000000), expected: u32(10) },
+ { input: u32Bits(0b00000000010000000000000000000000), expected: u32(9) },
+ { input: u32Bits(0b00000000100000000000000000000000), expected: u32(8) },
+ { input: u32Bits(0b00000001000000000000000000000000), expected: u32(7) },
+ { input: u32Bits(0b00000010000000000000000000000000), expected: u32(6) },
+ { input: u32Bits(0b00000100000000000000000000000000), expected: u32(5) },
+ { input: u32Bits(0b00001000000000000000000000000000), expected: u32(4) },
+ { input: u32Bits(0b00010000000000000000000000000000), expected: u32(3) },
+ { input: u32Bits(0b00100000000000000000000000000000), expected: u32(2) },
+ { input: u32Bits(0b01000000000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b10000000000000000000000000000000), expected: u32(0) },
+
+ // 1's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000011), expected: u32(30) },
+ { input: u32Bits(0b00000000000000000000000000000111), expected: u32(29) },
+ { input: u32Bits(0b00000000000000000000000000001111), expected: u32(28) },
+ { input: u32Bits(0b00000000000000000000000000011111), expected: u32(27) },
+ { input: u32Bits(0b00000000000000000000000000111111), expected: u32(26) },
+ { input: u32Bits(0b00000000000000000000000001111111), expected: u32(25) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(24) },
+ { input: u32Bits(0b00000000000000000000000111111111), expected: u32(23) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(22) },
+ { input: u32Bits(0b00000000000000000000011111111111), expected: u32(21) },
+ { input: u32Bits(0b00000000000000000000111111111111), expected: u32(20) },
+ { input: u32Bits(0b00000000000000000001111111111111), expected: u32(19) },
+ { input: u32Bits(0b00000000000000000011111111111111), expected: u32(18) },
+ { input: u32Bits(0b00000000000000000111111111111111), expected: u32(17) },
+ { input: u32Bits(0b00000000000000001111111111111111), expected: u32(16) },
+ { input: u32Bits(0b00000000000000011111111111111111), expected: u32(15) },
+ { input: u32Bits(0b00000000000000111111111111111111), expected: u32(14) },
+ { input: u32Bits(0b00000000000001111111111111111111), expected: u32(13) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(12) },
+ { input: u32Bits(0b00000000000111111111111111111111), expected: u32(11) },
+ { input: u32Bits(0b00000000001111111111111111111111), expected: u32(10) },
+ { input: u32Bits(0b00000000011111111111111111111111), expected: u32(9) },
+ { input: u32Bits(0b00000000111111111111111111111111), expected: u32(8) },
+ { input: u32Bits(0b00000001111111111111111111111111), expected: u32(7) },
+ { input: u32Bits(0b00000011111111111111111111111111), expected: u32(6) },
+ { input: u32Bits(0b00000111111111111111111111111111), expected: u32(5) },
+ { input: u32Bits(0b00001111111111111111111111111111), expected: u32(4) },
+ { input: u32Bits(0b00011111111111111111111111111111), expected: u32(3) },
+ { input: u32Bits(0b00111111111111111111111111111111), expected: u32(2) },
+ { input: u32Bits(0b01111111111111111111111111111111), expected: u32(1) },
+ { input: u32Bits(0b11111111111111111111111111111111), expected: u32(0) },
+
+ // random after leading 1
+ { input: u32Bits(0b00000000000000000000000000000110), expected: u32(29) },
+ { input: u32Bits(0b00000000000000000000000000001101), expected: u32(28) },
+ { input: u32Bits(0b00000000000000000000000000011101), expected: u32(27) },
+ { input: u32Bits(0b00000000000000000000000000111001), expected: u32(26) },
+ { input: u32Bits(0b00000000000000000000000001101111), expected: u32(25) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(24) },
+ { input: u32Bits(0b00000000000000000000000111101111), expected: u32(23) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(22) },
+ { input: u32Bits(0b00000000000000000000011111110001), expected: u32(21) },
+ { input: u32Bits(0b00000000000000000000111011011101), expected: u32(20) },
+ { input: u32Bits(0b00000000000000000001101101111111), expected: u32(19) },
+ { input: u32Bits(0b00000000000000000011111111011111), expected: u32(18) },
+ { input: u32Bits(0b00000000000000000101111001110101), expected: u32(17) },
+ { input: u32Bits(0b00000000000000001101111011110111), expected: u32(16) },
+ { input: u32Bits(0b00000000000000011111111111110011), expected: u32(15) },
+ { input: u32Bits(0b00000000000000111111111110111111), expected: u32(14) },
+ { input: u32Bits(0b00000000000001111111011111111111), expected: u32(13) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(12) },
+ { input: u32Bits(0b00000000000111110101011110111111), expected: u32(11) },
+ { input: u32Bits(0b00000000001111101111111111110111), expected: u32(10) },
+ { input: u32Bits(0b00000000011111111111010000101111), expected: u32(9) },
+ { input: u32Bits(0b00000000111111111111001111111011), expected: u32(8) },
+ { input: u32Bits(0b00000001111111011111101111111111), expected: u32(7) },
+ { input: u32Bits(0b00000011101011111011110111111011), expected: u32(6) },
+ { input: u32Bits(0b00000111111110111111111111111111), expected: u32(5) },
+ { input: u32Bits(0b00001111000000011011011110111111), expected: u32(4) },
+ { input: u32Bits(0b00011110101111011111111111111111), expected: u32(3) },
+ { input: u32Bits(0b00110110111111100111111110111101), expected: u32(2) },
+ { input: u32Bits(0b01010111111101111111011111011111), expected: u32(1) },
+ { input: u32Bits(0b11100010011110101101101110101111), expected: u32(0) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countLeadingZeros'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ { input: i32Bits(0b00000000000000000000000000000000), expected: i32(32) },
+
+ // One
+ { input: i32Bits(0b00000000000000000000000000000001), expected: i32(31) },
+
+ // 0's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000010), expected: i32(30) },
+ { input: i32Bits(0b00000000000000000000000000000100), expected: i32(29) },
+ { input: i32Bits(0b00000000000000000000000000001000), expected: i32(28) },
+ { input: i32Bits(0b00000000000000000000000000010000), expected: i32(27) },
+ { input: i32Bits(0b00000000000000000000000000100000), expected: i32(26) },
+ { input: i32Bits(0b00000000000000000000000001000000), expected: i32(25) },
+ { input: i32Bits(0b00000000000000000000000010000000), expected: i32(24) },
+ { input: i32Bits(0b00000000000000000000000100000000), expected: i32(23) },
+ { input: i32Bits(0b00000000000000000000001000000000), expected: i32(22) },
+ { input: i32Bits(0b00000000000000000000010000000000), expected: i32(21) },
+ { input: i32Bits(0b00000000000000000000100000000000), expected: i32(20) },
+ { input: i32Bits(0b00000000000000000001000000000000), expected: i32(19) },
+ { input: i32Bits(0b00000000000000000010000000000000), expected: i32(18) },
+ { input: i32Bits(0b00000000000000000100000000000000), expected: i32(17) },
+ { input: i32Bits(0b00000000000000001000000000000000), expected: i32(16) },
+ { input: i32Bits(0b00000000000000010000000000000000), expected: i32(15) },
+ { input: i32Bits(0b00000000000000100000000000000000), expected: i32(14) },
+ { input: i32Bits(0b00000000000001000000000000000000), expected: i32(13) },
+ { input: i32Bits(0b00000000000010000000000000000000), expected: i32(12) },
+ { input: i32Bits(0b00000000000100000000000000000000), expected: i32(11) },
+ { input: i32Bits(0b00000000001000000000000000000000), expected: i32(10) },
+ { input: i32Bits(0b00000000010000000000000000000000), expected: i32(9) },
+ { input: i32Bits(0b00000000100000000000000000000000), expected: i32(8) },
+ { input: i32Bits(0b00000001000000000000000000000000), expected: i32(7) },
+ { input: i32Bits(0b00000010000000000000000000000000), expected: i32(6) },
+ { input: i32Bits(0b00000100000000000000000000000000), expected: i32(5) },
+ { input: i32Bits(0b00001000000000000000000000000000), expected: i32(4) },
+ { input: i32Bits(0b00010000000000000000000000000000), expected: i32(3) },
+ { input: i32Bits(0b00100000000000000000000000000000), expected: i32(2) },
+ { input: i32Bits(0b01000000000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b10000000000000000000000000000000), expected: i32(0) },
+
+ // 1's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000011), expected: i32(30) },
+ { input: i32Bits(0b00000000000000000000000000000111), expected: i32(29) },
+ { input: i32Bits(0b00000000000000000000000000001111), expected: i32(28) },
+ { input: i32Bits(0b00000000000000000000000000011111), expected: i32(27) },
+ { input: i32Bits(0b00000000000000000000000000111111), expected: i32(26) },
+ { input: i32Bits(0b00000000000000000000000001111111), expected: i32(25) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(24) },
+ { input: i32Bits(0b00000000000000000000000111111111), expected: i32(23) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(22) },
+ { input: i32Bits(0b00000000000000000000011111111111), expected: i32(21) },
+ { input: i32Bits(0b00000000000000000000111111111111), expected: i32(20) },
+ { input: i32Bits(0b00000000000000000001111111111111), expected: i32(19) },
+ { input: i32Bits(0b00000000000000000011111111111111), expected: i32(18) },
+ { input: i32Bits(0b00000000000000000111111111111111), expected: i32(17) },
+ { input: i32Bits(0b00000000000000001111111111111111), expected: i32(16) },
+ { input: i32Bits(0b00000000000000011111111111111111), expected: i32(15) },
+ { input: i32Bits(0b00000000000000111111111111111111), expected: i32(14) },
+ { input: i32Bits(0b00000000000001111111111111111111), expected: i32(13) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(12) },
+ { input: i32Bits(0b00000000000111111111111111111111), expected: i32(11) },
+ { input: i32Bits(0b00000000001111111111111111111111), expected: i32(10) },
+ { input: i32Bits(0b00000000011111111111111111111111), expected: i32(9) },
+ { input: i32Bits(0b00000000111111111111111111111111), expected: i32(8) },
+ { input: i32Bits(0b00000001111111111111111111111111), expected: i32(7) },
+ { input: i32Bits(0b00000011111111111111111111111111), expected: i32(6) },
+ { input: i32Bits(0b00000111111111111111111111111111), expected: i32(5) },
+ { input: i32Bits(0b00001111111111111111111111111111), expected: i32(4) },
+ { input: i32Bits(0b00011111111111111111111111111111), expected: i32(3) },
+ { input: i32Bits(0b00111111111111111111111111111111), expected: i32(2) },
+ { input: i32Bits(0b01111111111111111111111111111111), expected: i32(1) },
+ { input: i32Bits(0b11111111111111111111111111111111), expected: i32(0) },
+
+ // random after leading 1
+ { input: i32Bits(0b00000000000000000000000000000110), expected: i32(29) },
+ { input: i32Bits(0b00000000000000000000000000001101), expected: i32(28) },
+ { input: i32Bits(0b00000000000000000000000000011101), expected: i32(27) },
+ { input: i32Bits(0b00000000000000000000000000111001), expected: i32(26) },
+ { input: i32Bits(0b00000000000000000000000001101111), expected: i32(25) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(24) },
+ { input: i32Bits(0b00000000000000000000000111101111), expected: i32(23) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(22) },
+ { input: i32Bits(0b00000000000000000000011111110001), expected: i32(21) },
+ { input: i32Bits(0b00000000000000000000111011011101), expected: i32(20) },
+ { input: i32Bits(0b00000000000000000001101101111111), expected: i32(19) },
+ { input: i32Bits(0b00000000000000000011111111011111), expected: i32(18) },
+ { input: i32Bits(0b00000000000000000101111001110101), expected: i32(17) },
+ { input: i32Bits(0b00000000000000001101111011110111), expected: i32(16) },
+ { input: i32Bits(0b00000000000000011111111111110011), expected: i32(15) },
+ { input: i32Bits(0b00000000000000111111111110111111), expected: i32(14) },
+ { input: i32Bits(0b00000000000001111111011111111111), expected: i32(13) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(12) },
+ { input: i32Bits(0b00000000000111110101011110111111), expected: i32(11) },
+ { input: i32Bits(0b00000000001111101111111111110111), expected: i32(10) },
+ { input: i32Bits(0b00000000011111111111010000101111), expected: i32(9) },
+ { input: i32Bits(0b00000000111111111111001111111011), expected: i32(8) },
+ { input: i32Bits(0b00000001111111011111101111111111), expected: i32(7) },
+ { input: i32Bits(0b00000011101011111011110111111011), expected: i32(6) },
+ { input: i32Bits(0b00000111111110111111111111111111), expected: i32(5) },
+ { input: i32Bits(0b00001111000000011011011110111111), expected: i32(4) },
+ { input: i32Bits(0b00011110101111011111111111111111), expected: i32(3) },
+ { input: i32Bits(0b00110110111111100111111110111101), expected: i32(2) },
+ { input: i32Bits(0b01010111111101111111011111011111), expected: i32(1) },
+ { input: i32Bits(0b11100010011110101101101110101111), expected: i32(0) },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js
new file mode 100644
index 0000000000..b6a82da5e5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countOneBits.spec.js
@@ -0,0 +1,246 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'countOneBits' builtin function
+
+S is i32 or u32
+T is S or vecN<S>
+@const fn countOneBits(e: T ) -> T
+The number of 1 bits in the representation of e.
+Also known as "population count".
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeU32, u32Bits, u32, TypeI32, i32Bits, i32 } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countOneBits'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ { input: u32Bits(0b00000000000000000000000000000000), expected: u32(0) },
+
+ // One
+ { input: u32Bits(0b00000000000000000000000000000001), expected: u32(1) },
+
+ // 0's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000010), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000000100), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000001000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000010000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000100000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000001000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000010000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000100000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000001000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000010000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000100000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000001000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000010000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000100000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000001000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000010000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000000100000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000001000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000010000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000000100000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000001000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000010000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000000100000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000001000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000010000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00000100000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00001000000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00010000000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b00100000000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b01000000000000000000000000000000), expected: u32(1) },
+ { input: u32Bits(0b10000000000000000000000000000000), expected: u32(1) },
+
+ // 1's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000011), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000000111), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000001111), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000011111), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000000111111), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000001111111), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000000111111111), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000011111111111), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000000111111111111), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000001111111111111), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000011111111111111), expected: u32(14) },
+ { input: u32Bits(0b00000000000000000111111111111111), expected: u32(15) },
+ { input: u32Bits(0b00000000000000001111111111111111), expected: u32(16) },
+ { input: u32Bits(0b00000000000000011111111111111111), expected: u32(17) },
+ { input: u32Bits(0b00000000000000111111111111111111), expected: u32(18) },
+ { input: u32Bits(0b00000000000001111111111111111111), expected: u32(19) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(20) },
+ { input: u32Bits(0b00000000000111111111111111111111), expected: u32(21) },
+ { input: u32Bits(0b00000000001111111111111111111111), expected: u32(22) },
+ { input: u32Bits(0b00000000011111111111111111111111), expected: u32(23) },
+ { input: u32Bits(0b00000000111111111111111111111111), expected: u32(24) },
+ { input: u32Bits(0b00000001111111111111111111111111), expected: u32(25) },
+ { input: u32Bits(0b00000011111111111111111111111111), expected: u32(26) },
+ { input: u32Bits(0b00000111111111111111111111111111), expected: u32(27) },
+ { input: u32Bits(0b00001111111111111111111111111111), expected: u32(28) },
+ { input: u32Bits(0b00011111111111111111111111111111), expected: u32(29) },
+ { input: u32Bits(0b00111111111111111111111111111111), expected: u32(30) },
+ { input: u32Bits(0b01111111111111111111111111111111), expected: u32(31) },
+ { input: u32Bits(0b11111111111111111111111111111111), expected: u32(32) },
+
+ // random after leading 1
+ { input: u32Bits(0b00000000000000000000000000000110), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001101), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000011101), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000111001), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000001101111), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000000111101111), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000011111110001), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000111011011101), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000001101101111111), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000011111111011111), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000101111001110101), expected: u32(10) },
+ { input: u32Bits(0b00000000000000001101111011110111), expected: u32(13) },
+ { input: u32Bits(0b00000000000000011111111111110011), expected: u32(15) },
+ { input: u32Bits(0b00000000000000111111111110111111), expected: u32(17) },
+ { input: u32Bits(0b00000000000001111111011111111111), expected: u32(18) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(20) },
+ { input: u32Bits(0b00000000000111110101011110111111), expected: u32(17) },
+ { input: u32Bits(0b00000000001111101111111111110111), expected: u32(20) },
+ { input: u32Bits(0b00000000011111111111010000101111), expected: u32(17) },
+ { input: u32Bits(0b00000000111111111111001111111011), expected: u32(21) },
+ { input: u32Bits(0b00000001111111011111101111111111), expected: u32(23) },
+ { input: u32Bits(0b00000011101011111011110111111011), expected: u32(21) },
+ { input: u32Bits(0b00000111111110111111111111111111), expected: u32(26) },
+ { input: u32Bits(0b00001111000000011011011110111111), expected: u32(18) },
+ { input: u32Bits(0b00011110101111011111111111111111), expected: u32(26) },
+ { input: u32Bits(0b00110110111111100111111110111101), expected: u32(24) },
+ { input: u32Bits(0b01010111111101111111011111011111), expected: u32(26) },
+ { input: u32Bits(0b11100010011110101101101110101111), expected: u32(21) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countOneBits'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ { input: i32Bits(0b00000000000000000000000000000000), expected: i32(0) },
+
+ // One
+ { input: i32Bits(0b00000000000000000000000000000001), expected: i32(1) },
+
+ // 0's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000010), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000000100), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000001000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000010000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000100000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000001000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000010000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000100000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000001000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000010000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000100000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000001000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000010000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000100000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000001000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000010000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000000100000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000001000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000010000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000000100000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000001000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000010000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000000100000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000001000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000010000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00000100000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00001000000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00010000000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b00100000000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b01000000000000000000000000000000), expected: i32(1) },
+ { input: i32Bits(0b10000000000000000000000000000000), expected: i32(1) },
+
+ // 1's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000011), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000000111), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000001111), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000011111), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000000111111), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000001111111), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000000111111111), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000011111111111), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000000111111111111), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000001111111111111), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000011111111111111), expected: i32(14) },
+ { input: i32Bits(0b00000000000000000111111111111111), expected: i32(15) },
+ { input: i32Bits(0b00000000000000001111111111111111), expected: i32(16) },
+ { input: i32Bits(0b00000000000000011111111111111111), expected: i32(17) },
+ { input: i32Bits(0b00000000000000111111111111111111), expected: i32(18) },
+ { input: i32Bits(0b00000000000001111111111111111111), expected: i32(19) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(20) },
+ { input: i32Bits(0b00000000000111111111111111111111), expected: i32(21) },
+ { input: i32Bits(0b00000000001111111111111111111111), expected: i32(22) },
+ { input: i32Bits(0b00000000011111111111111111111111), expected: i32(23) },
+ { input: i32Bits(0b00000000111111111111111111111111), expected: i32(24) },
+ { input: i32Bits(0b00000001111111111111111111111111), expected: i32(25) },
+ { input: i32Bits(0b00000011111111111111111111111111), expected: i32(26) },
+ { input: i32Bits(0b00000111111111111111111111111111), expected: i32(27) },
+ { input: i32Bits(0b00001111111111111111111111111111), expected: i32(28) },
+ { input: i32Bits(0b00011111111111111111111111111111), expected: i32(29) },
+ { input: i32Bits(0b00111111111111111111111111111111), expected: i32(30) },
+ { input: i32Bits(0b01111111111111111111111111111111), expected: i32(31) },
+ { input: i32Bits(0b11111111111111111111111111111111), expected: i32(32) },
+
+ // random after leading 1
+ { input: i32Bits(0b00000000000000000000000000000110), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001101), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000011101), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000111001), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000001101111), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000000111101111), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000011111110001), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000111011011101), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000001101101111111), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000011111111011111), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000101111001110101), expected: i32(10) },
+ { input: i32Bits(0b00000000000000001101111011110111), expected: i32(13) },
+ { input: i32Bits(0b00000000000000011111111111110011), expected: i32(15) },
+ { input: i32Bits(0b00000000000000111111111110111111), expected: i32(17) },
+ { input: i32Bits(0b00000000000001111111011111111111), expected: i32(18) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(20) },
+ { input: i32Bits(0b00000000000111110101011110111111), expected: i32(17) },
+ { input: i32Bits(0b00000000001111101111111111110111), expected: i32(20) },
+ { input: i32Bits(0b00000000011111111111010000101111), expected: i32(17) },
+ { input: i32Bits(0b00000000111111111111001111111011), expected: i32(21) },
+ { input: i32Bits(0b00000001111111011111101111111111), expected: i32(23) },
+ { input: i32Bits(0b00000011101011111011110111111011), expected: i32(21) },
+ { input: i32Bits(0b00000111111110111111111111111111), expected: i32(26) },
+ { input: i32Bits(0b00001111000000011011011110111111), expected: i32(18) },
+ { input: i32Bits(0b00011110101111011111111111111111), expected: i32(26) },
+ { input: i32Bits(0b00110110111111100111111110111101), expected: i32(24) },
+ { input: i32Bits(0b01010111111101111111011111011111), expected: i32(26) },
+ { input: i32Bits(0b11100010011110101101101110101111), expected: i32(21) },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js
new file mode 100644
index 0000000000..e0a0421702
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/countTrailingZeros.spec.js
@@ -0,0 +1,247 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'countTrailingZeros' builtin function
+
+S is i32 or u32
+T is S or vecN<S>
+@const fn countTrailingZeros(e: T ) -> T
+The number of consecutive 0 bits starting from the least significant bit of e,
+when T is a scalar type.
+Component-wise when T is a vector.
+Also known as "ctz" in some languages.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countTrailingZeros'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ { input: u32Bits(0b00000000000000000000000000000000), expected: u32(32) },
+
+ // High bit
+ { input: u32Bits(0b10000000000000000000000000000000), expected: u32(31) },
+
+ // 0's before trailing 1
+ { input: u32Bits(0b00000000000000000000000000000001), expected: u32(0) },
+ { input: u32Bits(0b00000000000000000000000000000010), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000000100), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001000), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000010000), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000100000), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000001000000), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000010000000), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000100000000), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001000000000), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000010000000000), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000100000000000), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000001000000000000), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000010000000000000), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000100000000000000), expected: u32(14) },
+ { input: u32Bits(0b00000000000000001000000000000000), expected: u32(15) },
+ { input: u32Bits(0b00000000000000010000000000000000), expected: u32(16) },
+ { input: u32Bits(0b00000000000000100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b00000000000001000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b00000000000010000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b00000000000100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b00000000001000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b00000000010000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b00000000100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b00000001000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b00000010000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b00000100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b00001000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b00010000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b00100000000000000000000000000000), expected: u32(29) },
+ { input: u32Bits(0b01000000000000000000000000000000), expected: u32(30) },
+
+ // 1's before trailing 1
+ { input: u32Bits(0b11111111111111111111111111111111), expected: u32(0) },
+ { input: u32Bits(0b11111111111111111111111111111110), expected: u32(1) },
+ { input: u32Bits(0b11111111111111111111111111111100), expected: u32(2) },
+ { input: u32Bits(0b11111111111111111111111111111000), expected: u32(3) },
+ { input: u32Bits(0b11111111111111111111111111110000), expected: u32(4) },
+ { input: u32Bits(0b11111111111111111111111111100000), expected: u32(5) },
+ { input: u32Bits(0b11111111111111111111111111000000), expected: u32(6) },
+ { input: u32Bits(0b11111111111111111111111110000000), expected: u32(7) },
+ { input: u32Bits(0b11111111111111111111111100000000), expected: u32(8) },
+ { input: u32Bits(0b11111111111111111111111000000000), expected: u32(9) },
+ { input: u32Bits(0b11111111111111111111110000000000), expected: u32(10) },
+ { input: u32Bits(0b11111111111111111111100000000000), expected: u32(11) },
+ { input: u32Bits(0b11111111111111111111000000000000), expected: u32(12) },
+ { input: u32Bits(0b11111111111111111110000000000000), expected: u32(13) },
+ { input: u32Bits(0b11111111111111111100000000000000), expected: u32(14) },
+ { input: u32Bits(0b11111111111111111000000000000000), expected: u32(15) },
+ { input: u32Bits(0b11111111111111110000000000000000), expected: u32(16) },
+ { input: u32Bits(0b11111111111111100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b11111111111111000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b11111111111110000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b11111111111100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b11111111111000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b11111111110000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b11111111100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b11111111000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b11111110000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b11111100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b11111000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b11110000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b11100000000000000000000000000000), expected: u32(29) },
+ { input: u32Bits(0b11000000000000000000000000000000), expected: u32(30) },
+
+ // random before trailing 1
+ { input: u32Bits(0b11110000001111111101111010001111), expected: u32(0) },
+ { input: u32Bits(0b11011110111111100101110011110010), expected: u32(1) },
+ { input: u32Bits(0b11110111011011111111010000111100), expected: u32(2) },
+ { input: u32Bits(0b11010011011101111111010011101000), expected: u32(3) },
+ { input: u32Bits(0b11010111110111110001111110110000), expected: u32(4) },
+ { input: u32Bits(0b11111101111101111110101111100000), expected: u32(5) },
+ { input: u32Bits(0b11111001111011111001111011000000), expected: u32(6) },
+ { input: u32Bits(0b11001110110111110111111010000000), expected: u32(7) },
+ { input: u32Bits(0b11101111011111101110101100000000), expected: u32(8) },
+ { input: u32Bits(0b11111101111011111111111000000000), expected: u32(9) },
+ { input: u32Bits(0b10011111011101110110110000000000), expected: u32(10) },
+ { input: u32Bits(0b11111111101101111011100000000000), expected: u32(11) },
+ { input: u32Bits(0b11111011010110111011000000000000), expected: u32(12) },
+ { input: u32Bits(0b00111101010000111010000000000000), expected: u32(13) },
+ { input: u32Bits(0b11111011110001101100000000000000), expected: u32(14) },
+ { input: u32Bits(0b10111111010111111000000000000000), expected: u32(15) },
+ { input: u32Bits(0b11011101111010110000000000000000), expected: u32(16) },
+ { input: u32Bits(0b01110100110110100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b11100111001011000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b11111001110110000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b00110100100100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b11111010011000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b00000010110000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b11100111100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b00101101000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b11011010000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b11010100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b10111000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b01110000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b10100000000000000000000000000000), expected: u32(29) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('countTrailingZeros'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ { input: i32Bits(0b00000000000000000000000000000000), expected: i32(32) },
+
+ // High bit
+ { input: i32Bits(0b10000000000000000000000000000000), expected: i32(31) },
+
+ // 0's before trailing 1
+ { input: i32Bits(0b00000000000000000000000000000001), expected: i32(0) },
+ { input: i32Bits(0b00000000000000000000000000000010), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000000100), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001000), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000010000), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000100000), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000001000000), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000010000000), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000100000000), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001000000000), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000010000000000), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000100000000000), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000001000000000000), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000010000000000000), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000100000000000000), expected: i32(14) },
+ { input: i32Bits(0b00000000000000001000000000000000), expected: i32(15) },
+ { input: i32Bits(0b00000000000000010000000000000000), expected: i32(16) },
+ { input: i32Bits(0b00000000000000100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b00000000000001000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b00000000000010000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b00000000000100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b00000000001000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b00000000010000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b00000000100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b00000001000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b00000010000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b00000100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b00001000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b00010000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b00100000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b01000000000000000000000000000000), expected: i32(30) },
+
+ // 1's before trailing 1
+ { input: i32Bits(0b11111111111111111111111111111111), expected: i32(0) },
+ { input: i32Bits(0b11111111111111111111111111111110), expected: i32(1) },
+ { input: i32Bits(0b11111111111111111111111111111100), expected: i32(2) },
+ { input: i32Bits(0b11111111111111111111111111111000), expected: i32(3) },
+ { input: i32Bits(0b11111111111111111111111111110000), expected: i32(4) },
+ { input: i32Bits(0b11111111111111111111111111100000), expected: i32(5) },
+ { input: i32Bits(0b11111111111111111111111111000000), expected: i32(6) },
+ { input: i32Bits(0b11111111111111111111111110000000), expected: i32(7) },
+ { input: i32Bits(0b11111111111111111111111100000000), expected: i32(8) },
+ { input: i32Bits(0b11111111111111111111111000000000), expected: i32(9) },
+ { input: i32Bits(0b11111111111111111111110000000000), expected: i32(10) },
+ { input: i32Bits(0b11111111111111111111100000000000), expected: i32(11) },
+ { input: i32Bits(0b11111111111111111111000000000000), expected: i32(12) },
+ { input: i32Bits(0b11111111111111111110000000000000), expected: i32(13) },
+ { input: i32Bits(0b11111111111111111100000000000000), expected: i32(14) },
+ { input: i32Bits(0b11111111111111111000000000000000), expected: i32(15) },
+ { input: i32Bits(0b11111111111111110000000000000000), expected: i32(16) },
+ { input: i32Bits(0b11111111111111100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b11111111111111000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b11111111111110000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b11111111111100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b11111111111000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b11111111110000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b11111111100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b11111111000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b11111110000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b11111100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b11111000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b11110000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b11100000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b11000000000000000000000000000000), expected: i32(30) },
+
+ // random before trailing 1
+ { input: i32Bits(0b11110000001111111101111010001111), expected: i32(0) },
+ { input: i32Bits(0b11011110111111100101110011110010), expected: i32(1) },
+ { input: i32Bits(0b11110111011011111111010000111100), expected: i32(2) },
+ { input: i32Bits(0b11010011011101111111010011101000), expected: i32(3) },
+ { input: i32Bits(0b11010111110111110001111110110000), expected: i32(4) },
+ { input: i32Bits(0b11111101111101111110101111100000), expected: i32(5) },
+ { input: i32Bits(0b11111001111011111001111011000000), expected: i32(6) },
+ { input: i32Bits(0b11001110110111110111111010000000), expected: i32(7) },
+ { input: i32Bits(0b11101111011111101110101100000000), expected: i32(8) },
+ { input: i32Bits(0b11111101111011111111111000000000), expected: i32(9) },
+ { input: i32Bits(0b10011111011101110110110000000000), expected: i32(10) },
+ { input: i32Bits(0b11111111101101111011100000000000), expected: i32(11) },
+ { input: i32Bits(0b11111011010110111011000000000000), expected: i32(12) },
+ { input: i32Bits(0b00111101010000111010000000000000), expected: i32(13) },
+ { input: i32Bits(0b11111011110001101100000000000000), expected: i32(14) },
+ { input: i32Bits(0b10111111010111111000000000000000), expected: i32(15) },
+ { input: i32Bits(0b11011101111010110000000000000000), expected: i32(16) },
+ { input: i32Bits(0b01110100110110100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b11100111001011000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b11111001110110000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b00110100100100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b11111010011000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b00000010110000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b11100111100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b00101101000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b11011010000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b11010100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b10111000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b01110000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b10100000000000000000000000000000), expected: i32(29) },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js
new file mode 100644
index 0000000000..ce177245dc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/cross.spec.js
@@ -0,0 +1,67 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'cross' builtin function
+
+T is AbstractFloat, f32, or f16
+@const fn cross(e1: vec3<T> ,e2: vec3<T>) -> vec3<T>
+Returns the cross product of e1 and e2.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { crossInterval } from '../../../../../util/f32_interval.js';
+import { vectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateVectorPairToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('cross', {
+ f32_const: () => {
+ return generateVectorPairToVectorCases(
+ vectorF32Range(3),
+ vectorF32Range(3),
+ 'f32-only',
+ crossInterval
+ );
+ },
+ f32_non_const: () => {
+ return generateVectorPairToVectorCases(
+ vectorF32Range(3),
+ vectorF32Range(3),
+ 'unfiltered',
+ crossInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(
+ t,
+ builtin('cross'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32)],
+ TypeVec(3, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js
new file mode 100644
index 0000000000..fd002a1009
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/degrees.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'degrees' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<T>
+@const fn degrees(e1: T ) -> T
+Converts radians to degrees, approximating e1 × 180 ÷ π. Component-wise when T is a vector
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { degreesInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('degrees', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'f32-only', degreesInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', degreesInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('degrees'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js
new file mode 100644
index 0000000000..07c8a73039
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/determinant.spec.js
@@ -0,0 +1,33 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'determinant' builtin function
+
+T is AbstractFloat, f32, or f16
+@const determinant(e: matCxC<T> ) -> T
+Returns the determinant of e.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('dimension', [2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('dimension', [2, 3, 4]))
+ .unimplemented();
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('dimension', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js
new file mode 100644
index 0000000000..2b967b5871
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/distance.spec.js
@@ -0,0 +1,172 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'distance' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn distance(e1: T ,e2: T ) -> f32
+Returns the distance between e1 and e2 (e.g. length(e1-e2)).
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { distanceInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, sparseVectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import {
+ allInputSources,
+ generateBinaryToF32IntervalCases,
+ generateVectorPairToF32IntervalCases,
+ run,
+} from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('distance', {
+ f32_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ distanceInterval
+ );
+ },
+ f32_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ distanceInterval
+ );
+ },
+ f32_vec2_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'f32-only',
+ distanceInterval
+ );
+ },
+ f32_vec2_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'unfiltered',
+ distanceInterval
+ );
+ },
+ f32_vec3_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'f32-only',
+ distanceInterval
+ );
+ },
+ f32_vec3_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'unfiltered',
+ distanceInterval
+ );
+ },
+ f32_vec4_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'f32-only',
+ distanceInterval
+ );
+ },
+ f32_vec4_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'unfiltered',
+ distanceInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('distance'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(
+ t,
+ builtin('distance'),
+ [TypeVec(2, TypeF32), TypeVec(2, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(
+ t,
+ builtin('distance'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(
+ t,
+ builtin('distance'),
+ [TypeVec(4, TypeF32), TypeVec(4, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js
new file mode 100644
index 0000000000..dcd701f4b3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dot.spec.js
@@ -0,0 +1,160 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dot' builtin function
+
+T is AbstractInt, AbstractFloat, i32, u32, f32, or f16
+@const fn dot(e1: vecN<T>,e2: vecN<T>) -> T
+Returns the dot product of e1 and e2.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { dotInterval } from '../../../../../util/f32_interval.js';
+import { sparseVectorF32Range, vectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateVectorPairToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// vec3 and vec4 require calculating all possible permutations, so their runtime is much longer per test, so only using
+// sparse vectors for them
+export const d = makeCaseCache('dot', {
+ f32_vec2_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ vectorF32Range(2),
+ vectorF32Range(2),
+ 'f32-only',
+ dotInterval
+ );
+ },
+ f32_vec2_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ vectorF32Range(2),
+ vectorF32Range(2),
+ 'unfiltered',
+ dotInterval
+ );
+ },
+ f32_vec3_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'f32-only',
+ dotInterval
+ );
+ },
+ f32_vec3_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'unfiltered',
+ dotInterval
+ );
+ },
+ f32_vec4_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'f32-only',
+ dotInterval
+ );
+ },
+ f32_vec4_non_const: () => {
+ return generateVectorPairToF32IntervalCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'unfiltered',
+ dotInterval
+ );
+ },
+});
+
+g.test('abstract_int')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`abstract int tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`abstract float test`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(
+ t,
+ builtin('dot'),
+ [TypeVec(2, TypeF32), TypeVec(2, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(
+ t,
+ builtin('dot'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(
+ t,
+ builtin('dot'),
+ [TypeVec(4, TypeF32), TypeVec(4, TypeF32)],
+ TypeF32,
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js
new file mode 100644
index 0000000000..c4d5413b70
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdx.spec.js
@@ -0,0 +1,22 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdx' builtin function
+
+T is f32 or vecN<f32>
+fn dpdx(e:T) -> T
+Partial derivative of e with respect to window x coordinates.
+The result is the same as either dpdxFine(e) or dpdxCoarse(e).
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js
new file mode 100644
index 0000000000..8b37d1982b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.js
@@ -0,0 +1,21 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdxCoarse' builtin function
+
+T is f32 or vecN<f32>
+fn dpdxCoarse(e:T) ->T
+Returns the partial derivative of e with respect to window x coordinates using local differences.
+This may result in fewer unique positions that dpdxFine(e).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js
new file mode 100644
index 0000000000..57c1f49b47
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdxFine' builtin function
+
+T is f32 or vecN<f32>
+fn dpdxFine(e:T) ->T
+Returns the partial derivative of e with respect to window x coordinates.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js
new file mode 100644
index 0000000000..9e9debdf58
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdy.spec.js
@@ -0,0 +1,21 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdy' builtin function
+
+T is f32 or vecN<f32>
+fn dpdy(e:T) ->T
+Partial derivative of e with respect to window y coordinates.
+The result is the same as either dpdyFine(e) or dpdyCoarse(e).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js
new file mode 100644
index 0000000000..f477a88330
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyCoarse.spec.js
@@ -0,0 +1,21 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdyCoarse' builtin function
+
+T is f32 or vecN<f32>
+fn dpdyCoarse(e:T) ->T
+Returns the partial derivative of e with respect to window y coordinates using local differences.
+This may result in fewer unique positions that dpdyFine(e).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 test`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js
new file mode 100644
index 0000000000..dc986daeec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/dpdyFine.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'dpdyFine' builtin function
+
+T is f32 or vecN<f32>
+fn dpdyFine(e:T) ->T
+Returns the partial derivative of e with respect to window y coordinates.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js
new file mode 100644
index 0000000000..2733284ffe
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'exp' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn exp(e1: T ) -> T
+Returns the natural exponentiation of e1 (e.g. e^e1). Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { expInterval } from '../../../../../util/f32_interval.js';
+import { biasedRange, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// floor(ln(max f32 value)) = 88, so exp(88) will be within range of a f32, but exp(89) will not
+// floor(ln(max f64 value)) = 709, so exp(709) can be handled by the testing framework, but exp(710) will misbehave
+const inputs = [
+ 0, // Returns 1 by definition
+ -89, // Returns subnormal value
+ kValue.f32.negative.min, // Closest to returning 0 as possible
+ ...biasedRange(kValue.f32.negative.max, -88, 100),
+ ...biasedRange(kValue.f32.positive.min, 88, 100),
+ ...linearRange(89, 709, 10), // Overflows f32, but not f64
+];
+
+export const d = makeCaseCache('exp', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', expInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', expInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('exp'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js
new file mode 100644
index 0000000000..ebca038ee6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/exp2.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'exp2' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn exp2(e: T ) -> T
+Returns 2 raised to the power e (e.g. 2^e). Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { exp2Interval } from '../../../../../util/f32_interval.js';
+import { biasedRange, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// floor(log2(max f32 value)) = 127, so exp2(127) will be within range of a f32, but exp2(128) will not
+// floor(ln(max f64 value)) = 1023, so exp2(1023) can be handled by the testing framework, but exp2(1024) will misbehave
+const inputs = [
+ 0, // Returns 1 by definition
+ -128, // Returns subnormal value
+ kValue.f32.negative.min, // Closest to returning 0 as possible
+ ...biasedRange(kValue.f32.negative.max, -127, 100),
+ ...biasedRange(kValue.f32.positive.min, 127, 100),
+ ...linearRange(128, 1023, 10), // Overflows f32, but not f64
+];
+
+export const d = makeCaseCache('exp2', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', exp2Interval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', exp2Interval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('exp2'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js
new file mode 100644
index 0000000000..cc6b466092
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/extractBits.spec.js
@@ -0,0 +1,338 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'extractBits' builtin function
+
+T is u32 or vecN<u32>
+@const fn extractBits(e: T, offset: u32, count: u32) -> T
+Reads bits from an integer, without sign extension.
+
+When T is a scalar type, then:
+ w is the bit width of T
+ o = min(offset,w)
+ c = min(count, w - o)
+
+The result is 0 if c is 0.
+Otherwise, bits 0..c-1 of the result are copied from bits o..o+c-1 of e.
+Other bits of the result are 0.
+Component-wise when T is a vector.
+
+
+T is i32 or vecN<i32>
+@const fn extractBits(e: T, offset: u32, count: u32) -> T
+Reads bits from an integer, with sign extension.
+
+When T is a scalar type, then:
+ w is the bit width of T
+ o = min(offset,w)
+ c = min(count, w - o)
+
+The result is 0 if c is 0.
+Otherwise, bits 0..c-1 of the result are copied from bits o..o+c-1 of e.
+Other bits of the result are the same as bit c-1 of the result.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import {
+ i32Bits,
+ TypeI32,
+ u32,
+ TypeU32,
+ u32Bits,
+ vec2,
+ vec3,
+ vec4,
+ TypeVec,
+} from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('width', [1, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+
+ const T = t.params.width === 1 ? TypeU32 : TypeVec(t.params.width, TypeU32);
+
+ const V = (x, y, z, w) => {
+ y = y === undefined ? x : y;
+ z = z === undefined ? x : z;
+ w = w === undefined ? x : w;
+
+ switch (t.params.width) {
+ case 1:
+ return u32Bits(x);
+ case 2:
+ return vec2(u32Bits(x), u32Bits(y));
+ case 3:
+ return vec3(u32Bits(x), u32Bits(y), u32Bits(z));
+ default:
+ return vec4(u32Bits(x), u32Bits(y), u32Bits(z), u32Bits(w));
+ }
+ };
+
+ const all_1 = V(0b11111111111111111111111111111111);
+ const all_0 = V(0b00000000000000000000000000000000);
+ const low_1 = V(0b00000000000000000000000000000001);
+ const high_1 = V(0b10000000000000000000000000000000);
+ const pattern = V(
+ 0b00000000000111011100000000000000,
+ 0b11111111111000000011111111111111,
+ 0b00000000010101010101000000000000,
+ 0b00000000001010101010100000000000
+ );
+
+ const cases = [
+ { input: [all_0, u32(0), u32(32)], expected: all_0 },
+ { input: [all_0, u32(1), u32(10)], expected: all_0 },
+ { input: [all_0, u32(2), u32(5)], expected: all_0 },
+ { input: [all_0, u32(0), u32(1)], expected: all_0 },
+ { input: [all_0, u32(31), u32(1)], expected: all_0 },
+
+ { input: [all_1, u32(0), u32(32)], expected: all_1 },
+ {
+ input: [all_1, u32(1), u32(10)],
+ expected: V(0b00000000000000000000001111111111),
+ },
+ {
+ input: [all_1, u32(2), u32(5)],
+ expected: V(0b00000000000000000000000000011111),
+ },
+ { input: [all_1, u32(0), u32(1)], expected: low_1 },
+ { input: [all_1, u32(31), u32(1)], expected: low_1 },
+
+ // Patterns
+ { input: [pattern, u32(0), u32(32)], expected: pattern },
+ {
+ input: [pattern, u32(1), u32(31)],
+ expected: V(
+ 0b00000000000011101110000000000000,
+ 0b01111111111100000001111111111111,
+ 0b00000000001010101010100000000000,
+ 0b00000000000101010101010000000000
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(18)],
+ expected: V(
+ 0b00000000000000000000000001110111,
+ 0b00000000000000111111111110000000,
+ 0b00000000000000000000000101010101,
+ 0b00000000000000000000000010101010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(7)],
+ expected: V(
+ 0b00000000000000000000000001110111,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000001010101,
+ 0b00000000000000000000000000101010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(4)],
+ expected: V(
+ 0b00000000000000000000000000000111,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000101,
+ 0b00000000000000000000000000001010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(3)],
+ expected: V(
+ 0b00000000000000000000000000000111,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000101,
+ 0b00000000000000000000000000000010
+ ),
+ },
+ {
+ input: [pattern, u32(18), u32(3)],
+ expected: V(
+ 0b00000000000000000000000000000111,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000101,
+ 0b00000000000000000000000000000010
+ ),
+ },
+ { input: [low_1, u32(0), u32(1)], expected: low_1 },
+ { input: [high_1, u32(31), u32(1)], expected: low_1 },
+
+ // Zero count
+ { input: [all_1, u32(0), u32(0)], expected: all_0 },
+ { input: [all_0, u32(0), u32(0)], expected: all_0 },
+ { input: [low_1, u32(0), u32(0)], expected: all_0 },
+ { input: [high_1, u32(31), u32(0)], expected: all_0 },
+ { input: [pattern, u32(0), u32(0)], expected: all_0 },
+ ];
+
+ if (t.params.inputSource !== 'const') {
+ cases.push(
+ ...[
+ // End overflow
+ { input: [low_1, u32(0), u32(99)], expected: low_1 },
+ { input: [high_1, u32(31), u32(99)], expected: low_1 },
+ { input: [pattern, u32(0), u32(99)], expected: pattern },
+ {
+ input: [pattern, u32(14), u32(99)],
+ expected: V(
+ 0b00000000000000000000000001110111,
+ 0b00000000000000111111111110000000,
+ 0b00000000000000000000000101010101,
+ 0b00000000000000000000000010101010
+ ),
+ },
+ ]
+ );
+ }
+
+ await run(t, builtin('extractBits'), [T, TypeU32, TypeU32], T, cfg, cases);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('width', [1, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+
+ const T = t.params.width === 1 ? TypeI32 : TypeVec(t.params.width, TypeI32);
+
+ const V = (x, y, z, w) => {
+ y = y === undefined ? x : y;
+ z = z === undefined ? x : z;
+ w = w === undefined ? x : w;
+
+ switch (t.params.width) {
+ case 1:
+ return i32Bits(x);
+ case 2:
+ return vec2(i32Bits(x), i32Bits(y));
+ case 3:
+ return vec3(i32Bits(x), i32Bits(y), i32Bits(z));
+ default:
+ return vec4(i32Bits(x), i32Bits(y), i32Bits(z), i32Bits(w));
+ }
+ };
+
+ const all_1 = V(0b11111111111111111111111111111111);
+ const all_0 = V(0b00000000000000000000000000000000);
+ const low_1 = V(0b00000000000000000000000000000001);
+ const high_1 = V(0b10000000000000000000000000000000);
+ const pattern = V(
+ 0b00000000000111011100000000000000,
+ 0b11111111111000000011111111111111,
+ 0b00000000010101010101000000000000,
+ 0b00000000001010101010100000000000
+ );
+
+ const cases = [
+ { input: [all_0, u32(0), u32(32)], expected: all_0 },
+ { input: [all_0, u32(1), u32(10)], expected: all_0 },
+ { input: [all_0, u32(2), u32(5)], expected: all_0 },
+ { input: [all_0, u32(0), u32(1)], expected: all_0 },
+ { input: [all_0, u32(31), u32(1)], expected: all_0 },
+
+ { input: [all_1, u32(0), u32(32)], expected: all_1 },
+ { input: [all_1, u32(1), u32(10)], expected: all_1 },
+ { input: [all_1, u32(2), u32(5)], expected: all_1 },
+ { input: [all_1, u32(0), u32(1)], expected: all_1 },
+ { input: [all_1, u32(31), u32(1)], expected: all_1 },
+
+ // Patterns
+ { input: [pattern, u32(0), u32(32)], expected: pattern },
+ {
+ input: [pattern, u32(1), u32(31)],
+ expected: V(
+ 0b00000000000011101110000000000000,
+ 0b11111111111100000001111111111111,
+ 0b00000000001010101010100000000000,
+ 0b00000000000101010101010000000000
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(18)],
+ expected: V(
+ 0b00000000000000000000000001110111,
+ 0b11111111111111111111111110000000,
+ 0b00000000000000000000000101010101,
+ 0b00000000000000000000000010101010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(7)],
+ expected: V(
+ 0b11111111111111111111111111110111,
+ 0b00000000000000000000000000000000,
+ 0b11111111111111111111111111010101,
+ 0b00000000000000000000000000101010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(4)],
+ expected: V(
+ 0b00000000000000000000000000000111,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000101,
+ 0b11111111111111111111111111111010
+ ),
+ },
+ {
+ input: [pattern, u32(14), u32(3)],
+ expected: V(
+ 0b11111111111111111111111111111111,
+ 0b00000000000000000000000000000000,
+ 0b11111111111111111111111111111101,
+ 0b00000000000000000000000000000010
+ ),
+ },
+ {
+ input: [pattern, u32(18), u32(3)],
+ expected: V(
+ 0b11111111111111111111111111111111,
+ 0b00000000000000000000000000000000,
+ 0b11111111111111111111111111111101,
+ 0b00000000000000000000000000000010
+ ),
+ },
+ { input: [low_1, u32(0), u32(1)], expected: all_1 },
+ { input: [high_1, u32(31), u32(1)], expected: all_1 },
+
+ // Zero count
+ { input: [all_1, u32(0), u32(0)], expected: all_0 },
+ { input: [all_0, u32(0), u32(0)], expected: all_0 },
+ { input: [low_1, u32(0), u32(0)], expected: all_0 },
+ { input: [high_1, u32(31), u32(0)], expected: all_0 },
+ { input: [pattern, u32(0), u32(0)], expected: all_0 },
+ ];
+
+ if (t.params.inputSource !== 'const') {
+ cases.push(
+ ...[
+ // End overflow
+ { input: [low_1, u32(0), u32(99)], expected: low_1 },
+ { input: [high_1, u32(31), u32(99)], expected: all_1 },
+ { input: [pattern, u32(0), u32(99)], expected: pattern },
+ {
+ input: [pattern, u32(14), u32(99)],
+ expected: V(
+ 0b00000000000000000000000001110111,
+ 0b11111111111111111111111110000000,
+ 0b00000000000000000000000101010101,
+ 0b00000000000000000000000010101010
+ ),
+ },
+ ]
+ );
+ }
+
+ await run(t, builtin('extractBits'), [T, TypeU32, TypeU32], T, cfg, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js
new file mode 100644
index 0000000000..3f3991f3c7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/faceForward.spec.js
@@ -0,0 +1,195 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'faceForward' builtin function
+
+T is vecN<AbstractFloat>, vecN<f32>, or vecN<f16>
+@const fn faceForward(e1: T ,e2: T ,e3: T ) -> T
+Returns e1 if dot(e2,e3) is negative, and -e1 otherwise.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { anyOf } from '../../../../../util/compare.js';
+import { f32, TypeF32, TypeVec, Vector } from '../../../../../util/conversion.js';
+import { faceForwardIntervals } from '../../../../../util/f32_interval.js';
+import { cartesianProduct, quantizeToF32, sparseVectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// Using a bespoke implementation of make*Case and generate*Cases here
+// since faceForwardIntervals is the only builtin with the API signature
+// (vec, vec, vec) -> vec
+//
+// Additionally faceForward has significant complexities around it due to the
+// fact that `dot` is calculated in it s operation, but the result of dot isn't
+// used to calculate the builtin's result.
+
+/**
+ * @returns a Case for `faceForward`
+ * @param x the `x` param for the case
+ * @param y the `y` param for the case
+ * @param z the `z` param for the case
+ * @param check what interval checking to apply
+ * */
+function makeCaseF32(x, y, z, check) {
+ x = x.map(quantizeToF32);
+ y = y.map(quantizeToF32);
+ z = z.map(quantizeToF32);
+
+ const x_f32 = x.map(f32);
+ const y_f32 = y.map(f32);
+ const z_f32 = z.map(f32);
+
+ const results = faceForwardIntervals(x, y, z);
+ if (check === 'f32-only' && results.some(r => r === undefined)) {
+ return undefined;
+ }
+
+ // Stripping the undefined results, since undefined is used to signal that an OOB
+ // could occur within the calculation that isn't reflected in the result
+ // intervals.
+ const define_results = results.filter(r => r !== undefined);
+
+ return {
+ input: [new Vector(x_f32), new Vector(y_f32), new Vector(z_f32)],
+ expected: anyOf(...define_results),
+ };
+}
+
+/**
+ * @returns an array of Cases for `faceForward`
+ * @param xs array of inputs to try for the `x` param
+ * @param ys array of inputs to try for the `y` param
+ * @param zs array of inputs to try for the `z` param
+ * @param check what interval checking to apply
+ */
+function generateCasesF32(xs, ys, zs, check) {
+ // Cannot use `cartesianProduct` here due to heterogeneous param types
+ return cartesianProduct(xs, ys, zs)
+ .map(e => makeCaseF32(e[0], e[1], e[2], check))
+ .filter(c => c !== undefined);
+}
+
+export const d = makeCaseCache('faceForward', {
+ f32_vec2_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'f32-only'
+ );
+ },
+ f32_vec2_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'unfiltered'
+ );
+ },
+ f32_vec3_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'f32-only'
+ );
+ },
+ f32_vec3_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'unfiltered'
+ );
+ },
+ f32_vec4_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'f32-only'
+ );
+ },
+ f32_vec4_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'unfiltered'
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(
+ t,
+ builtin('faceForward'),
+ [TypeVec(2, TypeF32), TypeVec(2, TypeF32), TypeVec(2, TypeF32)],
+ TypeVec(2, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(
+ t,
+ builtin('faceForward'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32), TypeVec(3, TypeF32)],
+ TypeVec(3, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(
+ t,
+ builtin('faceForward'),
+ [TypeVec(4, TypeF32), TypeVec(4, TypeF32), TypeVec(4, TypeF32)],
+ TypeVec(4, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js
new file mode 100644
index 0000000000..f556dba788
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstLeadingBit.spec.js
@@ -0,0 +1,344 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'firstLeadingBit' builtin function
+
+T is u32 or vecN<u32>
+@const fn firstLeadingBit(e: T ) -> T
+For scalar T, the result is: T(-1) if e is zero.
+Otherwise the position of the most significant 1 bit in e.
+Component-wise when T is a vector.
+
+T is i32 or vecN<i32>
+@const fn firstLeadingBit(e: T ) -> T
+For scalar T, the result is: -1 if e is 0 or -1.
+Otherwise the position of the most significant bit in e that is different from e’s sign bit.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('firstLeadingBit'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ { input: u32Bits(0b00000000000000000000000000000000), expected: u32(-1) },
+
+ // One
+ { input: u32Bits(0b00000000000000000000000000000001), expected: u32(0) },
+
+ // 0's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000010), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000000100), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001000), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000010000), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000100000), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000001000000), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000010000000), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000100000000), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001000000000), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000010000000000), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000100000000000), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000001000000000000), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000010000000000000), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000100000000000000), expected: u32(14) },
+ { input: u32Bits(0b00000000000000001000000000000000), expected: u32(15) },
+ { input: u32Bits(0b00000000000000010000000000000000), expected: u32(16) },
+ { input: u32Bits(0b00000000000000100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b00000000000001000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b00000000000010000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b00000000000100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b00000000001000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b00000000010000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b00000000100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b00000001000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b00000010000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b00000100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b00001000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b00010000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b00100000000000000000000000000000), expected: u32(29) },
+ { input: u32Bits(0b01000000000000000000000000000000), expected: u32(30) },
+ { input: u32Bits(0b10000000000000000000000000000000), expected: u32(31) },
+
+ // 1's after leading 1
+ { input: u32Bits(0b00000000000000000000000000000011), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000000111), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001111), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000011111), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000111111), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000001111111), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000111111111), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000011111111111), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000111111111111), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000001111111111111), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000011111111111111), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000111111111111111), expected: u32(14) },
+ { input: u32Bits(0b00000000000000001111111111111111), expected: u32(15) },
+ { input: u32Bits(0b00000000000000011111111111111111), expected: u32(16) },
+ { input: u32Bits(0b00000000000000111111111111111111), expected: u32(17) },
+ { input: u32Bits(0b00000000000001111111111111111111), expected: u32(18) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(19) },
+ { input: u32Bits(0b00000000000111111111111111111111), expected: u32(20) },
+ { input: u32Bits(0b00000000001111111111111111111111), expected: u32(21) },
+ { input: u32Bits(0b00000000011111111111111111111111), expected: u32(22) },
+ { input: u32Bits(0b00000000111111111111111111111111), expected: u32(23) },
+ { input: u32Bits(0b00000001111111111111111111111111), expected: u32(24) },
+ { input: u32Bits(0b00000011111111111111111111111111), expected: u32(25) },
+ { input: u32Bits(0b00000111111111111111111111111111), expected: u32(26) },
+ { input: u32Bits(0b00001111111111111111111111111111), expected: u32(27) },
+ { input: u32Bits(0b00011111111111111111111111111111), expected: u32(28) },
+ { input: u32Bits(0b00111111111111111111111111111111), expected: u32(29) },
+ { input: u32Bits(0b01111111111111111111111111111111), expected: u32(30) },
+ { input: u32Bits(0b11111111111111111111111111111111), expected: u32(31) },
+
+ // random after leading 1
+ { input: u32Bits(0b00000000000000000000000000000110), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001101), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000011101), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000111001), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000001101111), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000011111111), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000111101111), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001111111111), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000011111110001), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000111011011101), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000001101101111111), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000011111111011111), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000101111001110101), expected: u32(14) },
+ { input: u32Bits(0b00000000000000001101111011110111), expected: u32(15) },
+ { input: u32Bits(0b00000000000000011111111111110011), expected: u32(16) },
+ { input: u32Bits(0b00000000000000111111111110111111), expected: u32(17) },
+ { input: u32Bits(0b00000000000001111111011111111111), expected: u32(18) },
+ { input: u32Bits(0b00000000000011111111111111111111), expected: u32(19) },
+ { input: u32Bits(0b00000000000111110101011110111111), expected: u32(20) },
+ { input: u32Bits(0b00000000001111101111111111110111), expected: u32(21) },
+ { input: u32Bits(0b00000000011111111111010000101111), expected: u32(22) },
+ { input: u32Bits(0b00000000111111111111001111111011), expected: u32(23) },
+ { input: u32Bits(0b00000001111111011111101111111111), expected: u32(24) },
+ { input: u32Bits(0b00000011101011111011110111111011), expected: u32(25) },
+ { input: u32Bits(0b00000111111110111111111111111111), expected: u32(26) },
+ { input: u32Bits(0b00001111000000011011011110111111), expected: u32(27) },
+ { input: u32Bits(0b00011110101111011111111111111111), expected: u32(28) },
+ { input: u32Bits(0b00110110111111100111111110111101), expected: u32(29) },
+ { input: u32Bits(0b01010111111101111111011111011111), expected: u32(30) },
+ { input: u32Bits(0b11100010011110101101101110101111), expected: u32(31) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('firstLeadingBit'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ { input: i32Bits(0b00000000000000000000000000000000), expected: i32(-1) },
+
+ // One
+ { input: i32Bits(0b00000000000000000000000000000001), expected: i32(0) },
+
+ // Positive: 0's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000010), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000000100), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001000), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000010000), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000100000), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000001000000), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000010000000), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000100000000), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001000000000), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000010000000000), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000100000000000), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000001000000000000), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000010000000000000), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000100000000000000), expected: i32(14) },
+ { input: i32Bits(0b00000000000000001000000000000000), expected: i32(15) },
+ { input: i32Bits(0b00000000000000010000000000000000), expected: i32(16) },
+ { input: i32Bits(0b00000000000000100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b00000000000001000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b00000000000010000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b00000000000100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b00000000001000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b00000000010000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b00000000100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b00000001000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b00000010000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b00000100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b00001000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b00010000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b00100000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b01000000000000000000000000000000), expected: i32(30) },
+
+ // Negative: 0's after leading 0
+ { input: i32Bits(0b11111111111111111111111111111110), expected: i32(0) },
+ { input: i32Bits(0b11111111111111111111111111111100), expected: i32(1) },
+ { input: i32Bits(0b11111111111111111111111111111000), expected: i32(2) },
+ { input: i32Bits(0b11111111111111111111111111110000), expected: i32(3) },
+ { input: i32Bits(0b11111111111111111111111111100000), expected: i32(4) },
+ { input: i32Bits(0b11111111111111111111111111000000), expected: i32(5) },
+ { input: i32Bits(0b11111111111111111111111110000000), expected: i32(6) },
+ { input: i32Bits(0b11111111111111111111111100000000), expected: i32(7) },
+ { input: i32Bits(0b11111111111111111111111000000000), expected: i32(8) },
+ { input: i32Bits(0b11111111111111111111110000000000), expected: i32(9) },
+ { input: i32Bits(0b11111111111111111111100000000000), expected: i32(10) },
+ { input: i32Bits(0b11111111111111111111000000000000), expected: i32(11) },
+ { input: i32Bits(0b11111111111111111110000000000000), expected: i32(12) },
+ { input: i32Bits(0b11111111111111111100000000000000), expected: i32(13) },
+ { input: i32Bits(0b11111111111111111000000000000000), expected: i32(14) },
+ { input: i32Bits(0b11111111111111110000000000000000), expected: i32(15) },
+ { input: i32Bits(0b11111111111111100000000000000000), expected: i32(16) },
+ { input: i32Bits(0b11111111111111000000000000000000), expected: i32(17) },
+ { input: i32Bits(0b11111111111110000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b11111111111100000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b11111111111000000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b11111111110000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b11111111100000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b11111111000000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b11111110000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b11111100000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b11111000000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b11110000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b11100000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b11000000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b10000000000000000000000000000000), expected: i32(30) },
+
+ // Positive: 1's after leading 1
+ { input: i32Bits(0b00000000000000000000000000000011), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000000111), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001111), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000011111), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000111111), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000001111111), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000111111111), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000011111111111), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000111111111111), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000001111111111111), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000011111111111111), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000111111111111111), expected: i32(14) },
+ { input: i32Bits(0b00000000000000001111111111111111), expected: i32(15) },
+ { input: i32Bits(0b00000000000000011111111111111111), expected: i32(16) },
+ { input: i32Bits(0b00000000000000111111111111111111), expected: i32(17) },
+ { input: i32Bits(0b00000000000001111111111111111111), expected: i32(18) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(19) },
+ { input: i32Bits(0b00000000000111111111111111111111), expected: i32(20) },
+ { input: i32Bits(0b00000000001111111111111111111111), expected: i32(21) },
+ { input: i32Bits(0b00000000011111111111111111111111), expected: i32(22) },
+ { input: i32Bits(0b00000000111111111111111111111111), expected: i32(23) },
+ { input: i32Bits(0b00000001111111111111111111111111), expected: i32(24) },
+ { input: i32Bits(0b00000011111111111111111111111111), expected: i32(25) },
+ { input: i32Bits(0b00000111111111111111111111111111), expected: i32(26) },
+ { input: i32Bits(0b00001111111111111111111111111111), expected: i32(27) },
+ { input: i32Bits(0b00011111111111111111111111111111), expected: i32(28) },
+ { input: i32Bits(0b00111111111111111111111111111111), expected: i32(29) },
+ { input: i32Bits(0b01111111111111111111111111111111), expected: i32(30) },
+
+ // Negative: 1's after leading 0
+ { input: i32Bits(0b11111111111111111111111111111101), expected: i32(1) },
+ { input: i32Bits(0b11111111111111111111111111111011), expected: i32(2) },
+ { input: i32Bits(0b11111111111111111111111111110111), expected: i32(3) },
+ { input: i32Bits(0b11111111111111111111111111101111), expected: i32(4) },
+ { input: i32Bits(0b11111111111111111111111111011111), expected: i32(5) },
+ { input: i32Bits(0b11111111111111111111111110111111), expected: i32(6) },
+ { input: i32Bits(0b11111111111111111111111101111111), expected: i32(7) },
+ { input: i32Bits(0b11111111111111111111111011111111), expected: i32(8) },
+ { input: i32Bits(0b11111111111111111111110111111111), expected: i32(9) },
+ { input: i32Bits(0b11111111111111111111101111111111), expected: i32(10) },
+ { input: i32Bits(0b11111111111111111111011111111111), expected: i32(11) },
+ { input: i32Bits(0b11111111111111111110111111111111), expected: i32(12) },
+ { input: i32Bits(0b11111111111111111101111111111111), expected: i32(13) },
+ { input: i32Bits(0b11111111111111111011111111111111), expected: i32(14) },
+ { input: i32Bits(0b11111111111111110111111111111111), expected: i32(15) },
+ { input: i32Bits(0b11111111111111101111111111111111), expected: i32(16) },
+ { input: i32Bits(0b11111111111111011111111111111111), expected: i32(17) },
+ { input: i32Bits(0b11111111111110111111111111111111), expected: i32(18) },
+ { input: i32Bits(0b11111111111101111111111111111111), expected: i32(19) },
+ { input: i32Bits(0b11111111111011111111111111111111), expected: i32(20) },
+ { input: i32Bits(0b11111111110111111111111111111111), expected: i32(21) },
+ { input: i32Bits(0b11111111101111111111111111111111), expected: i32(22) },
+ { input: i32Bits(0b11111111011111111111111111111111), expected: i32(23) },
+ { input: i32Bits(0b11111110111111111111111111111111), expected: i32(24) },
+ { input: i32Bits(0b11111101111111111111111111111111), expected: i32(25) },
+ { input: i32Bits(0b11111011111111111111111111111111), expected: i32(26) },
+ { input: i32Bits(0b11110111111111111111111111111111), expected: i32(27) },
+ { input: i32Bits(0b11101111111111111111111111111111), expected: i32(28) },
+ { input: i32Bits(0b11011111111111111111111111111111), expected: i32(29) },
+ { input: i32Bits(0b10111111111111111111111111111111), expected: i32(30) },
+
+ // Positive: random after leading 1
+ { input: i32Bits(0b00000000000000000000000000000110), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001101), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000011101), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000111001), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000001101111), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000011111111), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000111101111), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001111111111), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000011111110001), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000111011011101), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000001101101111111), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000011111111011111), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000101111001110101), expected: i32(14) },
+ { input: i32Bits(0b00000000000000001101111011110111), expected: i32(15) },
+ { input: i32Bits(0b00000000000000011111111111110011), expected: i32(16) },
+ { input: i32Bits(0b00000000000000111111111110111111), expected: i32(17) },
+ { input: i32Bits(0b00000000000001111111011111111111), expected: i32(18) },
+ { input: i32Bits(0b00000000000011111111111111111111), expected: i32(19) },
+ { input: i32Bits(0b00000000000111110101011110111111), expected: i32(20) },
+ { input: i32Bits(0b00000000001111101111111111110111), expected: i32(21) },
+ { input: i32Bits(0b00000000011111111111010000101111), expected: i32(22) },
+ { input: i32Bits(0b00000000111111111111001111111011), expected: i32(23) },
+ { input: i32Bits(0b00000001111111011111101111111111), expected: i32(24) },
+ { input: i32Bits(0b00000011101011111011110111111011), expected: i32(25) },
+ { input: i32Bits(0b00000111111110111111111111111111), expected: i32(26) },
+ { input: i32Bits(0b00001111000000011011011110111111), expected: i32(27) },
+ { input: i32Bits(0b00011110101111011111111111111111), expected: i32(28) },
+ { input: i32Bits(0b00110110111111100111111110111101), expected: i32(29) },
+ { input: i32Bits(0b01010111111101111111011111011111), expected: i32(30) },
+
+ // Negative: random after leading 0
+ { input: i32Bits(0b11111111111111111111111111111010), expected: i32(2) },
+ { input: i32Bits(0b11111111111111111111111111110110), expected: i32(3) },
+ { input: i32Bits(0b11111111111111111111111111101101), expected: i32(4) },
+ { input: i32Bits(0b11111111111111111111111111011101), expected: i32(5) },
+ { input: i32Bits(0b11111111111111111111111110111001), expected: i32(6) },
+ { input: i32Bits(0b11111111111111111111111101101111), expected: i32(7) },
+ { input: i32Bits(0b11111111111111111111111011111111), expected: i32(8) },
+ { input: i32Bits(0b11111111111111111111110111101111), expected: i32(9) },
+ { input: i32Bits(0b11111111111111111111101111111111), expected: i32(10) },
+ { input: i32Bits(0b11111111111111111111011111110001), expected: i32(11) },
+ { input: i32Bits(0b11111111111111111110111011011101), expected: i32(12) },
+ { input: i32Bits(0b11111111111111111101101101111111), expected: i32(13) },
+ { input: i32Bits(0b11111111111111111011111111011111), expected: i32(14) },
+ { input: i32Bits(0b11111111111111110101111001110101), expected: i32(15) },
+ { input: i32Bits(0b11111111111111101101111011110111), expected: i32(16) },
+ { input: i32Bits(0b11111111111111011111111111110011), expected: i32(17) },
+ { input: i32Bits(0b11111111111110111111111110111111), expected: i32(18) },
+ { input: i32Bits(0b11111111111101111111011111111111), expected: i32(19) },
+ { input: i32Bits(0b11111111111011111111111111111111), expected: i32(20) },
+ { input: i32Bits(0b11111111110111110101011110111111), expected: i32(21) },
+ { input: i32Bits(0b11111111101111101111111111110111), expected: i32(22) },
+ { input: i32Bits(0b11111111011111111111010000101111), expected: i32(23) },
+ { input: i32Bits(0b11111110111111111111001111111011), expected: i32(24) },
+ { input: i32Bits(0b11111101111111011111101111111111), expected: i32(25) },
+ { input: i32Bits(0b11111011101011111011110111111011), expected: i32(26) },
+ { input: i32Bits(0b11110111111110111111111111111111), expected: i32(27) },
+ { input: i32Bits(0b11101111000000011011011110111111), expected: i32(28) },
+ { input: i32Bits(0b11011110101111011111111111111111), expected: i32(29) },
+ { input: i32Bits(0b10110110111111100111111110111101), expected: i32(30) },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js
new file mode 100644
index 0000000000..29c46690b6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/firstTrailingBit.spec.js
@@ -0,0 +1,247 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'firstTrailingBit' builtin function
+
+S is i32, u32
+T is S or vecN<S>
+@const fn firstTrailingBit(e: T ) -> T
+For scalar T, the result is: T(-1) if e is zero.
+Otherwise the position of the least significant 1 bit in e.
+Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { i32, i32Bits, TypeI32, u32, TypeU32, u32Bits } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('firstTrailingBit'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ { input: u32Bits(0b00000000000000000000000000000000), expected: u32(-1) },
+
+ // High bit
+ { input: u32Bits(0b10000000000000000000000000000000), expected: u32(31) },
+
+ // 0's before trailing 1
+ { input: u32Bits(0b00000000000000000000000000000001), expected: u32(0) },
+ { input: u32Bits(0b00000000000000000000000000000010), expected: u32(1) },
+ { input: u32Bits(0b00000000000000000000000000000100), expected: u32(2) },
+ { input: u32Bits(0b00000000000000000000000000001000), expected: u32(3) },
+ { input: u32Bits(0b00000000000000000000000000010000), expected: u32(4) },
+ { input: u32Bits(0b00000000000000000000000000100000), expected: u32(5) },
+ { input: u32Bits(0b00000000000000000000000001000000), expected: u32(6) },
+ { input: u32Bits(0b00000000000000000000000010000000), expected: u32(7) },
+ { input: u32Bits(0b00000000000000000000000100000000), expected: u32(8) },
+ { input: u32Bits(0b00000000000000000000001000000000), expected: u32(9) },
+ { input: u32Bits(0b00000000000000000000010000000000), expected: u32(10) },
+ { input: u32Bits(0b00000000000000000000100000000000), expected: u32(11) },
+ { input: u32Bits(0b00000000000000000001000000000000), expected: u32(12) },
+ { input: u32Bits(0b00000000000000000010000000000000), expected: u32(13) },
+ { input: u32Bits(0b00000000000000000100000000000000), expected: u32(14) },
+ { input: u32Bits(0b00000000000000001000000000000000), expected: u32(15) },
+ { input: u32Bits(0b00000000000000010000000000000000), expected: u32(16) },
+ { input: u32Bits(0b00000000000000100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b00000000000001000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b00000000000010000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b00000000000100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b00000000001000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b00000000010000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b00000000100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b00000001000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b00000010000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b00000100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b00001000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b00010000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b00100000000000000000000000000000), expected: u32(29) },
+ { input: u32Bits(0b01000000000000000000000000000000), expected: u32(30) },
+
+ // 1's before trailing 1
+ { input: u32Bits(0b11111111111111111111111111111111), expected: u32(0) },
+ { input: u32Bits(0b11111111111111111111111111111110), expected: u32(1) },
+ { input: u32Bits(0b11111111111111111111111111111100), expected: u32(2) },
+ { input: u32Bits(0b11111111111111111111111111111000), expected: u32(3) },
+ { input: u32Bits(0b11111111111111111111111111110000), expected: u32(4) },
+ { input: u32Bits(0b11111111111111111111111111100000), expected: u32(5) },
+ { input: u32Bits(0b11111111111111111111111111000000), expected: u32(6) },
+ { input: u32Bits(0b11111111111111111111111110000000), expected: u32(7) },
+ { input: u32Bits(0b11111111111111111111111100000000), expected: u32(8) },
+ { input: u32Bits(0b11111111111111111111111000000000), expected: u32(9) },
+ { input: u32Bits(0b11111111111111111111110000000000), expected: u32(10) },
+ { input: u32Bits(0b11111111111111111111100000000000), expected: u32(11) },
+ { input: u32Bits(0b11111111111111111111000000000000), expected: u32(12) },
+ { input: u32Bits(0b11111111111111111110000000000000), expected: u32(13) },
+ { input: u32Bits(0b11111111111111111100000000000000), expected: u32(14) },
+ { input: u32Bits(0b11111111111111111000000000000000), expected: u32(15) },
+ { input: u32Bits(0b11111111111111110000000000000000), expected: u32(16) },
+ { input: u32Bits(0b11111111111111100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b11111111111111000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b11111111111110000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b11111111111100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b11111111111000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b11111111110000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b11111111100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b11111111000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b11111110000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b11111100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b11111000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b11110000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b11100000000000000000000000000000), expected: u32(29) },
+ { input: u32Bits(0b11000000000000000000000000000000), expected: u32(30) },
+
+ // random before trailing 1
+ { input: u32Bits(0b11110000001111111101111010001111), expected: u32(0) },
+ { input: u32Bits(0b11011110111111100101110011110010), expected: u32(1) },
+ { input: u32Bits(0b11110111011011111111010000111100), expected: u32(2) },
+ { input: u32Bits(0b11010011011101111111010011101000), expected: u32(3) },
+ { input: u32Bits(0b11010111110111110001111110110000), expected: u32(4) },
+ { input: u32Bits(0b11111101111101111110101111100000), expected: u32(5) },
+ { input: u32Bits(0b11111001111011111001111011000000), expected: u32(6) },
+ { input: u32Bits(0b11001110110111110111111010000000), expected: u32(7) },
+ { input: u32Bits(0b11101111011111101110101100000000), expected: u32(8) },
+ { input: u32Bits(0b11111101111011111111111000000000), expected: u32(9) },
+ { input: u32Bits(0b10011111011101110110110000000000), expected: u32(10) },
+ { input: u32Bits(0b11111111101101111011100000000000), expected: u32(11) },
+ { input: u32Bits(0b11111011010110111011000000000000), expected: u32(12) },
+ { input: u32Bits(0b00111101010000111010000000000000), expected: u32(13) },
+ { input: u32Bits(0b11111011110001101100000000000000), expected: u32(14) },
+ { input: u32Bits(0b10111111010111111000000000000000), expected: u32(15) },
+ { input: u32Bits(0b11011101111010110000000000000000), expected: u32(16) },
+ { input: u32Bits(0b01110100110110100000000000000000), expected: u32(17) },
+ { input: u32Bits(0b11100111001011000000000000000000), expected: u32(18) },
+ { input: u32Bits(0b11111001110110000000000000000000), expected: u32(19) },
+ { input: u32Bits(0b00110100100100000000000000000000), expected: u32(20) },
+ { input: u32Bits(0b11111010011000000000000000000000), expected: u32(21) },
+ { input: u32Bits(0b00000010110000000000000000000000), expected: u32(22) },
+ { input: u32Bits(0b11100111100000000000000000000000), expected: u32(23) },
+ { input: u32Bits(0b00101101000000000000000000000000), expected: u32(24) },
+ { input: u32Bits(0b11011010000000000000000000000000), expected: u32(25) },
+ { input: u32Bits(0b11010100000000000000000000000000), expected: u32(26) },
+ { input: u32Bits(0b10111000000000000000000000000000), expected: u32(27) },
+ { input: u32Bits(0b01110000000000000000000000000000), expected: u32(28) },
+ { input: u32Bits(0b10100000000000000000000000000000), expected: u32(29) },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+ await run(t, builtin('firstTrailingBit'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ { input: i32Bits(0b00000000000000000000000000000000), expected: i32(-1) },
+
+ // High bit
+ { input: i32Bits(0b10000000000000000000000000000000), expected: i32(31) },
+
+ // 0's before trailing 1
+ { input: i32Bits(0b00000000000000000000000000000001), expected: i32(0) },
+ { input: i32Bits(0b00000000000000000000000000000010), expected: i32(1) },
+ { input: i32Bits(0b00000000000000000000000000000100), expected: i32(2) },
+ { input: i32Bits(0b00000000000000000000000000001000), expected: i32(3) },
+ { input: i32Bits(0b00000000000000000000000000010000), expected: i32(4) },
+ { input: i32Bits(0b00000000000000000000000000100000), expected: i32(5) },
+ { input: i32Bits(0b00000000000000000000000001000000), expected: i32(6) },
+ { input: i32Bits(0b00000000000000000000000010000000), expected: i32(7) },
+ { input: i32Bits(0b00000000000000000000000100000000), expected: i32(8) },
+ { input: i32Bits(0b00000000000000000000001000000000), expected: i32(9) },
+ { input: i32Bits(0b00000000000000000000010000000000), expected: i32(10) },
+ { input: i32Bits(0b00000000000000000000100000000000), expected: i32(11) },
+ { input: i32Bits(0b00000000000000000001000000000000), expected: i32(12) },
+ { input: i32Bits(0b00000000000000000010000000000000), expected: i32(13) },
+ { input: i32Bits(0b00000000000000000100000000000000), expected: i32(14) },
+ { input: i32Bits(0b00000000000000001000000000000000), expected: i32(15) },
+ { input: i32Bits(0b00000000000000010000000000000000), expected: i32(16) },
+ { input: i32Bits(0b00000000000000100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b00000000000001000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b00000000000010000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b00000000000100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b00000000001000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b00000000010000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b00000000100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b00000001000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b00000010000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b00000100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b00001000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b00010000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b00100000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b01000000000000000000000000000000), expected: i32(30) },
+
+ // 1's before trailing 1
+ { input: i32Bits(0b11111111111111111111111111111111), expected: i32(0) },
+ { input: i32Bits(0b11111111111111111111111111111110), expected: i32(1) },
+ { input: i32Bits(0b11111111111111111111111111111100), expected: i32(2) },
+ { input: i32Bits(0b11111111111111111111111111111000), expected: i32(3) },
+ { input: i32Bits(0b11111111111111111111111111110000), expected: i32(4) },
+ { input: i32Bits(0b11111111111111111111111111100000), expected: i32(5) },
+ { input: i32Bits(0b11111111111111111111111111000000), expected: i32(6) },
+ { input: i32Bits(0b11111111111111111111111110000000), expected: i32(7) },
+ { input: i32Bits(0b11111111111111111111111100000000), expected: i32(8) },
+ { input: i32Bits(0b11111111111111111111111000000000), expected: i32(9) },
+ { input: i32Bits(0b11111111111111111111110000000000), expected: i32(10) },
+ { input: i32Bits(0b11111111111111111111100000000000), expected: i32(11) },
+ { input: i32Bits(0b11111111111111111111000000000000), expected: i32(12) },
+ { input: i32Bits(0b11111111111111111110000000000000), expected: i32(13) },
+ { input: i32Bits(0b11111111111111111100000000000000), expected: i32(14) },
+ { input: i32Bits(0b11111111111111111000000000000000), expected: i32(15) },
+ { input: i32Bits(0b11111111111111110000000000000000), expected: i32(16) },
+ { input: i32Bits(0b11111111111111100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b11111111111111000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b11111111111110000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b11111111111100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b11111111111000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b11111111110000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b11111111100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b11111111000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b11111110000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b11111100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b11111000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b11110000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b11100000000000000000000000000000), expected: i32(29) },
+ { input: i32Bits(0b11000000000000000000000000000000), expected: i32(30) },
+
+ // random before trailing 1
+ { input: i32Bits(0b11110000001111111101111010001111), expected: i32(0) },
+ { input: i32Bits(0b11011110111111100101110011110010), expected: i32(1) },
+ { input: i32Bits(0b11110111011011111111010000111100), expected: i32(2) },
+ { input: i32Bits(0b11010011011101111111010011101000), expected: i32(3) },
+ { input: i32Bits(0b11010111110111110001111110110000), expected: i32(4) },
+ { input: i32Bits(0b11111101111101111110101111100000), expected: i32(5) },
+ { input: i32Bits(0b11111001111011111001111011000000), expected: i32(6) },
+ { input: i32Bits(0b11001110110111110111111010000000), expected: i32(7) },
+ { input: i32Bits(0b11101111011111101110101100000000), expected: i32(8) },
+ { input: i32Bits(0b11111101111011111111111000000000), expected: i32(9) },
+ { input: i32Bits(0b10011111011101110110110000000000), expected: i32(10) },
+ { input: i32Bits(0b11111111101101111011100000000000), expected: i32(11) },
+ { input: i32Bits(0b11111011010110111011000000000000), expected: i32(12) },
+ { input: i32Bits(0b00111101010000111010000000000000), expected: i32(13) },
+ { input: i32Bits(0b11111011110001101100000000000000), expected: i32(14) },
+ { input: i32Bits(0b10111111010111111000000000000000), expected: i32(15) },
+ { input: i32Bits(0b11011101111010110000000000000000), expected: i32(16) },
+ { input: i32Bits(0b01110100110110100000000000000000), expected: i32(17) },
+ { input: i32Bits(0b11100111001011000000000000000000), expected: i32(18) },
+ { input: i32Bits(0b11111001110110000000000000000000), expected: i32(19) },
+ { input: i32Bits(0b00110100100100000000000000000000), expected: i32(20) },
+ { input: i32Bits(0b11111010011000000000000000000000), expected: i32(21) },
+ { input: i32Bits(0b00000010110000000000000000000000), expected: i32(22) },
+ { input: i32Bits(0b11100111100000000000000000000000), expected: i32(23) },
+ { input: i32Bits(0b00101101000000000000000000000000), expected: i32(24) },
+ { input: i32Bits(0b11011010000000000000000000000000), expected: i32(25) },
+ { input: i32Bits(0b11010100000000000000000000000000), expected: i32(26) },
+ { input: i32Bits(0b10111000000000000000000000000000), expected: i32(27) },
+ { input: i32Bits(0b01110000000000000000000000000000), expected: i32(28) },
+ { input: i32Bits(0b10100000000000000000000000000000), expected: i32(29) },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js
new file mode 100644
index 0000000000..d0d0fda771
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/floor.spec.js
@@ -0,0 +1,67 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'floor' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn floor(e: T ) -> T
+Returns the floor of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { floorInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('floor', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Small positive numbers
+ 0.1,
+ 0.9,
+ 1.0,
+ 1.1,
+ 1.9,
+ // Small negative numbers
+ -0.1,
+ -0.9,
+ -1.0,
+ -1.1,
+ -1.9,
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ floorInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('floor'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js
new file mode 100644
index 0000000000..d5542849b7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fma.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'fma' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn fma(e1: T ,e2: T ,e3: T ) -> T
+Returns e1 * e2 + e3. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { fmaInterval } from '../../../../../util/f32_interval.js';
+import { sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateTernaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('fma', {
+ f32_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'f32-only',
+ fmaInterval
+ );
+ },
+ f32_non_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'unfiltered',
+ fmaInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('fma'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js
new file mode 100644
index 0000000000..d63b3c2763
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fract.spec.js
@@ -0,0 +1,69 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'fract' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn fract(e: T ) -> T
+Returns the fractional part of e, computed as e - floor(e).
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { fractInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('fract', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ 0.5, // 0.5 -> 0.5
+ 0.9, // ~0.9 -> ~0.9
+ 1, // 1 -> 0
+ 2, // 2 -> 0
+ 1.11, // ~1.11 -> ~0.11
+ 10.0001, // ~10.0001 -> ~0.0001
+ -0.1, // ~-0.1 -> ~0.9
+ -0.5, // -0.5 -> 0.5
+ -0.9, // ~-0.9 -> ~0.1
+ -1, // -1 -> 0
+ -2, // -2 -> 0
+ -1.11, // ~-1.11 -> ~0.89
+ -10.0001, // -10.0001 -> ~0.9999
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ fractInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('fract'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js
new file mode 100644
index 0000000000..e6b2861078
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/frexp.spec.js
@@ -0,0 +1,81 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'frexp' builtin function
+
+S is f32 or f16
+T is S or vecN<S>
+
+@const fn frexp(e: T) -> result_struct
+
+Splits e into a significand and exponent of the form significand * 2^exponent.
+Returns the result_struct for the appropriate overload.
+
+
+The magnitude of the significand is in the range of [0.5, 1.0) or 0.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('scalar_f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+struct __frexp_result {
+ sig : f32, // significand part
+ exp : i32 // exponent part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('scalar_f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f16 tests
+
+struct __frexp_result_f16 {
+ sig : f16, // significand part
+ exp : i32 // exponent part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('vector_f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+vecN<f32>
+
+struct __frexp_result_vecN {
+ sig : vecN<f32>, // significand part
+ exp : vecN<i32> // exponent part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('vector_f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+vecN<f16>
+
+struct __frexp_result_vecN_f16 {
+ sig : vecN<f16>, // significand part
+ exp : vecN<i32> // exponent part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidth.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidth.spec.js
new file mode 100644
index 0000000000..ee33a68ab4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidth.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'fwidth' builtin function
+
+T is f32 or vecN<f32>
+fn fwidth(e:T) ->T
+Returns abs(dpdx(e)) + abs(dpdy(e)).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthCoarse.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthCoarse.spec.js
new file mode 100644
index 0000000000..d5df428ebc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthCoarse.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'fwidthCoarse' builtin function
+
+T is f32 or vecN<f32>
+fn fwidthCoarse(e:T) ->T
+Returns abs(dpdxCoarse(e)) + abs(dpdyCoarse(e)).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthFine.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthFine.spec.js
new file mode 100644
index 0000000000..0bd0ad33d3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/fwidthFine.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'fwidthFine' builtin function
+
+T is f32 or vecN<f32>
+fn fwidthFine(e:T) ->T
+Returns abs(dpdxFine(e)) + abs(dpdyFine(e)).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#derivative-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js
new file mode 100644
index 0000000000..262aaa199a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/insertBits.spec.js
@@ -0,0 +1,387 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'insertBits' builtin function
+
+S is i32 or u32
+T is S or vecN<S>
+@const fn insertBits(e: T, newbits:T, offset: u32, count: u32) -> T Sets bits in an integer.
+
+When T is a scalar type, then:
+ w is the bit width of T
+ o = min(offset,w)
+ c = min(count, w - o)
+
+The result is e if c is 0.
+Otherwise, bits o..o+c-1 of the result are copied from bits 0..c-1 of newbits.
+Other bits of the result are copied from e.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import {
+ i32Bits,
+ TypeI32,
+ u32,
+ TypeU32,
+ u32Bits,
+ vec2,
+ vec3,
+ vec4,
+ TypeVec,
+} from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('integer')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`integer tests`)
+ .params(u =>
+ u
+ .combine('inputSource', allInputSources)
+ .combine('signed', [false, true])
+ .combine('width', [1, 2, 3, 4])
+ )
+ .fn(async t => {
+ const cfg = t.params;
+ const scalarType = t.params.signed ? TypeI32 : TypeU32;
+ const T = t.params.width === 1 ? scalarType : TypeVec(t.params.width, scalarType);
+
+ const V = (x, y, z, w) => {
+ y = y === undefined ? x : y;
+ z = z === undefined ? x : z;
+ w = w === undefined ? x : w;
+
+ if (t.params.signed) {
+ switch (t.params.width) {
+ case 1:
+ return i32Bits(x);
+ case 2:
+ return vec2(i32Bits(x), i32Bits(y));
+ case 3:
+ return vec3(i32Bits(x), i32Bits(y), i32Bits(z));
+ default:
+ return vec4(i32Bits(x), i32Bits(y), i32Bits(z), i32Bits(w));
+ }
+ } else {
+ switch (t.params.width) {
+ case 1:
+ return u32Bits(x);
+ case 2:
+ return vec2(u32Bits(x), u32Bits(y));
+ case 3:
+ return vec3(u32Bits(x), u32Bits(y), u32Bits(z));
+ default:
+ return vec4(u32Bits(x), u32Bits(y), u32Bits(z), u32Bits(w));
+ }
+ }
+ };
+
+ const all_1 = V(0b11111111111111111111111111111111);
+ const all_0 = V(0b00000000000000000000000000000000);
+ const low_1 = V(0b00000000000000000000000000000001);
+ const low_0 = V(0b11111111111111111111111111111110);
+ const high_1 = V(0b10000000000000000000000000000000);
+ const high_0 = V(0b01111111111111111111111111111111);
+ const pattern = V(
+ 0b10001001010100100010010100100010,
+ 0b11001110001100111000110011100011,
+ 0b10101010101010101010101010101010,
+ 0b01010101010101010101010101010101
+ );
+
+ const cases = [
+ { input: [all_0, all_0, u32(0), u32(32)], expected: all_0 },
+ { input: [all_0, all_0, u32(1), u32(10)], expected: all_0 },
+ { input: [all_0, all_0, u32(2), u32(5)], expected: all_0 },
+ { input: [all_0, all_0, u32(0), u32(1)], expected: all_0 },
+ { input: [all_0, all_0, u32(31), u32(1)], expected: all_0 },
+
+ { input: [all_0, all_1, u32(0), u32(32)], expected: all_1 },
+ { input: [all_1, all_0, u32(0), u32(32)], expected: all_0 },
+ { input: [all_0, all_1, u32(0), u32(1)], expected: low_1 },
+ { input: [all_1, all_0, u32(0), u32(1)], expected: low_0 },
+ { input: [all_0, all_1, u32(31), u32(1)], expected: high_1 },
+ { input: [all_1, all_0, u32(31), u32(1)], expected: high_0 },
+ { input: [all_0, all_1, u32(1), u32(10)], expected: V(0b00000000000000000000011111111110) },
+ { input: [all_1, all_0, u32(1), u32(10)], expected: V(0b11111111111111111111100000000001) },
+ { input: [all_0, all_1, u32(2), u32(5)], expected: V(0b00000000000000000000000001111100) },
+ { input: [all_1, all_0, u32(2), u32(5)], expected: V(0b11111111111111111111111110000011) },
+
+ // Patterns
+ { input: [all_0, pattern, u32(0), u32(32)], expected: pattern },
+ { input: [all_1, pattern, u32(0), u32(32)], expected: pattern },
+ {
+ input: [all_0, pattern, u32(1), u32(31)],
+ expected: V(
+ 0b00010010101001000100101001000100,
+ 0b10011100011001110001100111000110,
+ 0b01010101010101010101010101010100,
+ 0b10101010101010101010101010101010
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(1), u32(31)],
+ expected: V(
+ 0b00010010101001000100101001000101,
+ 0b10011100011001110001100111000111,
+ 0b01010101010101010101010101010101,
+ 0b10101010101010101010101010101011
+ ),
+ },
+ {
+ input: [all_0, pattern, u32(14), u32(18)],
+ expected: V(
+ 0b10001001010010001000000000000000,
+ 0b11100011001110001100000000000000,
+ 0b10101010101010101000000000000000,
+ 0b01010101010101010100000000000000
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(14), u32(18)],
+ expected: V(
+ 0b10001001010010001011111111111111,
+ 0b11100011001110001111111111111111,
+ 0b10101010101010101011111111111111,
+ 0b01010101010101010111111111111111
+ ),
+ },
+ {
+ input: [all_0, pattern, u32(14), u32(7)],
+ expected: V(
+ 0b00000000000010001000000000000000,
+ 0b00000000000110001100000000000000,
+ 0b00000000000010101000000000000000,
+ 0b00000000000101010100000000000000
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(14), u32(7)],
+ expected: V(
+ 0b11111111111010001011111111111111,
+ 0b11111111111110001111111111111111,
+ 0b11111111111010101011111111111111,
+ 0b11111111111101010111111111111111
+ ),
+ },
+ {
+ input: [all_0, pattern, u32(14), u32(4)],
+ expected: V(
+ 0b00000000000000001000000000000000,
+ 0b00000000000000001100000000000000,
+ 0b00000000000000101000000000000000,
+ 0b00000000000000010100000000000000
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(14), u32(4)],
+ expected: V(
+ 0b11111111111111001011111111111111,
+ 0b11111111111111001111111111111111,
+ 0b11111111111111101011111111111111,
+ 0b11111111111111010111111111111111
+ ),
+ },
+ {
+ input: [all_0, pattern, u32(14), u32(3)],
+ expected: V(
+ 0b00000000000000001000000000000000,
+ 0b00000000000000001100000000000000,
+ 0b00000000000000001000000000000000,
+ 0b00000000000000010100000000000000
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(14), u32(3)],
+ expected: V(
+ 0b11111111111111101011111111111111,
+ 0b11111111111111101111111111111111,
+ 0b11111111111111101011111111111111,
+ 0b11111111111111110111111111111111
+ ),
+ },
+ {
+ input: [all_0, pattern, u32(18), u32(3)],
+ expected: V(
+ 0b00000000000010000000000000000000,
+ 0b00000000000011000000000000000000,
+ 0b00000000000010000000000000000000,
+ 0b00000000000101000000000000000000
+ ),
+ },
+ {
+ input: [all_1, pattern, u32(18), u32(3)],
+ expected: V(
+ 0b11111111111010111111111111111111,
+ 0b11111111111011111111111111111111,
+ 0b11111111111010111111111111111111,
+ 0b11111111111101111111111111111111
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(1), u32(31)],
+ expected: V(
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000001,
+ 0b00000000000000000000000000000000,
+ 0b00000000000000000000000000000001
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(1), u32(31)],
+ expected: V(
+ 0b11111111111111111111111111111110,
+ 0b11111111111111111111111111111111,
+ 0b11111111111111111111111111111110,
+ 0b11111111111111111111111111111111
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(14), u32(18)],
+ expected: V(
+ 0b00000000000000000010010100100010,
+ 0b00000000000000000000110011100011,
+ 0b00000000000000000010101010101010,
+ 0b00000000000000000001010101010101
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(14), u32(18)],
+ expected: V(
+ 0b11111111111111111110010100100010,
+ 0b11111111111111111100110011100011,
+ 0b11111111111111111110101010101010,
+ 0b11111111111111111101010101010101
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(14), u32(7)],
+ expected: V(
+ 0b10001001010000000010010100100010,
+ 0b11001110001000000000110011100011,
+ 0b10101010101000000010101010101010,
+ 0b01010101010000000001010101010101
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(14), u32(7)],
+ expected: V(
+ 0b10001001010111111110010100100010,
+ 0b11001110001111111100110011100011,
+ 0b10101010101111111110101010101010,
+ 0b01010101010111111101010101010101
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(14), u32(4)],
+ expected: V(
+ 0b10001001010100000010010100100010,
+ 0b11001110001100000000110011100011,
+ 0b10101010101010000010101010101010,
+ 0b01010101010101000001010101010101
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(14), u32(4)],
+ expected: V(
+ 0b10001001010100111110010100100010,
+ 0b11001110001100111100110011100011,
+ 0b10101010101010111110101010101010,
+ 0b01010101010101111101010101010101
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(14), u32(3)],
+ expected: V(
+ 0b10001001010100100010010100100010,
+ 0b11001110001100100000110011100011,
+ 0b10101010101010100010101010101010,
+ 0b01010101010101000001010101010101
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(14), u32(3)],
+ expected: V(
+ 0b10001001010100111110010100100010,
+ 0b11001110001100111100110011100011,
+ 0b10101010101010111110101010101010,
+ 0b01010101010101011101010101010101
+ ),
+ },
+ {
+ input: [pattern, all_0, u32(18), u32(3)],
+ expected: V(
+ 0b10001001010000100010010100100010,
+ 0b11001110001000111000110011100011,
+ 0b10101010101000101010101010101010,
+ 0b01010101010000010101010101010101
+ ),
+ },
+ {
+ input: [pattern, all_1, u32(18), u32(3)],
+ expected: V(
+ 0b10001001010111100010010100100010,
+ 0b11001110001111111000110011100011,
+ 0b10101010101111101010101010101010,
+ 0b01010101010111010101010101010101
+ ),
+ },
+ {
+ input: [pattern, pattern, u32(18), u32(3)],
+ expected: V(
+ 0b10001001010010100010010100100010,
+ 0b11001110001011111000110011100011,
+ 0b10101010101010101010101010101010,
+ 0b01010101010101010101010101010101
+ ),
+ },
+ {
+ input: [pattern, pattern, u32(14), u32(7)],
+ expected: V(
+ 0b10001001010010001010010100100010,
+ 0b11001110001110001100110011100011,
+ 0b10101010101010101010101010101010,
+ 0b01010101010101010101010101010101
+ ),
+ },
+
+ // Zero count
+ { input: [pattern, all_1, u32(0), u32(0)], expected: pattern },
+ { input: [pattern, all_1, u32(1), u32(0)], expected: pattern },
+ { input: [pattern, all_1, u32(2), u32(0)], expected: pattern },
+ { input: [pattern, all_1, u32(31), u32(0)], expected: pattern },
+ { input: [pattern, all_1, u32(32), u32(0)], expected: pattern },
+ { input: [pattern, all_1, u32(0), u32(0)], expected: pattern },
+ ];
+
+ if (t.params.inputSource !== 'const') {
+ cases.push(
+ ...[
+ // Start overflow
+ { input: [all_0, pattern, u32(50), u32(3)], expected: all_0 },
+ { input: [all_1, pattern, u32(50), u32(3)], expected: all_1 },
+ { input: [pattern, pattern, u32(50), u32(3)], expected: pattern },
+
+ // End overflow
+ { input: [all_0, pattern, u32(0), u32(99)], expected: pattern },
+ { input: [all_1, pattern, u32(0), u32(99)], expected: pattern },
+ { input: [all_0, low_1, u32(31), u32(99)], expected: high_1 },
+ {
+ input: [pattern, pattern, u32(20), u32(99)],
+ expected: V(
+ 0b01010010001000100010010100100010,
+ 0b11001110001100111000110011100011,
+ 0b10101010101010101010101010101010,
+ 0b01010101010101010101010101010101
+ ),
+ },
+ ]
+ );
+ }
+
+ await run(t, builtin('insertBits'), [T, T, TypeU32, TypeU32], T, cfg, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js
new file mode 100644
index 0000000000..95f94ab37b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/inversesqrt.spec.js
@@ -0,0 +1,59 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'inverseSqrt' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn inverseSqrt(e: T ) -> T
+Returns the reciprocal of sqrt(e). Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { inverseSqrtInterval } from '../../../../../util/f32_interval.js';
+import { biasedRange, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('inverseSqrt', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // 0 < x <= 1 linearly spread
+ ...linearRange(kValue.f32.positive.min, 1, 100),
+ // 1 <= x < 2^32, biased towards 1
+ ...biasedRange(1, 2 ** 32, 1000),
+ ],
+
+ 'unfiltered',
+ inverseSqrtInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('inverseSqrt'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js
new file mode 100644
index 0000000000..edcbf54d9d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/ldexp.spec.js
@@ -0,0 +1,90 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'ldexp' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+
+K is AbstractInt, i32
+I is K or vecN<K>, where
+ I is a scalar if T is a scalar, or a vector when T is a vector
+
+@const fn ldexp(e1: T ,e2: I ) -> T
+Returns e1 * 2^e2. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { f32, i32, TypeF32, TypeI32 } from '../../../../../util/conversion.js';
+import { ldexpInterval } from '../../../../../util/f32_interval.js';
+import {
+ biasedRange,
+ fullF32Range,
+ fullI32Range,
+ quantizeToF32,
+ quantizeToI32,
+} from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const makeCase = (e1, e2) => {
+ // Due to the heterogeneous types of the params to ldexp (f32 & i32),
+ // makeBinaryToF32IntervalCase cannot be used here.
+ e1 = quantizeToF32(e1);
+ e2 = quantizeToI32(e2);
+ const expected = ldexpInterval(e1, e2);
+ return { input: [f32(e1), i32(e2)], expected };
+};
+
+export const d = makeCaseCache('ldexp', {
+ f32_non_const: () => {
+ const cases = [];
+ fullF32Range().forEach(e1 => {
+ fullI32Range().forEach(e2 => {
+ cases.push(makeCase(e1, e2));
+ });
+ });
+ return cases;
+ },
+ f32_const: () => {
+ const cases = [];
+ fullF32Range().forEach(e1 => {
+ biasedRange(-128, 128, 10).forEach(e2 => {
+ const val = e1 * Math.pow(2, e2);
+ if (val >= kValue.f32.negative.min && val <= kValue.f32.positive.max) {
+ cases.push(makeCase(e1, e2));
+ }
+ });
+ });
+ return cases;
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('ldexp'), [TypeF32, TypeI32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js
new file mode 100644
index 0000000000..1538d379dc
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/length.spec.js
@@ -0,0 +1,107 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'length' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn length(e: T ) -> f32
+Returns the length of e (e.g. abs(e) if T is a scalar, or sqrt(e[0]^2 + e[1]^2 + ...) if T is a vector).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { lengthInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, vectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import {
+ allInputSources,
+ generateUnaryToF32IntervalCases,
+ generateVectorToF32IntervalCases,
+ run,
+} from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('length', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', lengthInterval);
+ },
+ f32_vec2_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(2), 'f32-only', lengthInterval);
+ },
+ f32_vec2_non_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(2), 'unfiltered', lengthInterval);
+ },
+ f32_vec3_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(3), 'f32-only', lengthInterval);
+ },
+ f32_vec3_non_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(3), 'unfiltered', lengthInterval);
+ },
+ f32_vec4_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(4), 'f32-only', lengthInterval);
+ },
+ f32_vec4_non_const: () => {
+ return generateVectorToF32IntervalCases(vectorF32Range(4), 'unfiltered', lengthInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('length'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(t, builtin('length'), [TypeVec(2, TypeF32)], TypeF32, t.params, cases);
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(t, builtin('length'), [TypeVec(3, TypeF32)], TypeF32, t.params, cases);
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(t, builtin('length'), [TypeVec(4, TypeF32)], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js
new file mode 100644
index 0000000000..35675301c4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log.spec.js
@@ -0,0 +1,66 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'log' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn log(e: T ) -> T
+Returns the natural logarithm of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { logInterval } from '../../../../../util/f32_interval.js';
+import { biasedRange, fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// log's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] }
+const inputs = [
+ ...linearRange(kValue.f32.positive.min, 0.5, 20),
+ ...linearRange(0.5, 2.0, 20),
+ ...biasedRange(2.0, 2 ** 32, 1000),
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('log', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', logInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', logInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('log'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js
new file mode 100644
index 0000000000..20372f8272
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/log2.spec.js
@@ -0,0 +1,66 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'log2' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn log2(e: T ) -> T
+Returns the base-2 logarithm of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { log2Interval } from '../../../../../util/f32_interval.js';
+import { biasedRange, fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// log2's accuracy is defined in three regions { [0, 0.5), [0.5, 2.0], (2.0, +∞] }
+const inputs = [
+ ...linearRange(kValue.f32.positive.min, 0.5, 20),
+ ...linearRange(0.5, 2.0, 20),
+ ...biasedRange(2.0, 2 ** 32, 1000),
+ ...fullF32Range(),
+];
+
+export const d = makeCaseCache('log2', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'f32-only', log2Interval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(inputs, 'unfiltered', log2Interval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('log2'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js
new file mode 100644
index 0000000000..4cfe2cc915
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/max.spec.js
@@ -0,0 +1,109 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'max' builtin function
+
+S is AbstractInt, i32, or u32
+T is S or vecN<S>
+@const fn max(e1: T ,e2: T) -> T
+Returns e2 if e1 is less than e2, and e1 otherwise. Component-wise when T is a vector.
+
+S is AbstractFloat, f32, f16
+T is vecN<S>
+@const fn max(e1: T ,e2: T) -> T
+Returns e2 if e1 is less than e2, and e1 otherwise.
+If one operand is a NaN, the other is returned.
+If both operands are NaNs, a NaN is returned.
+Component-wise when T is a vector.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { i32, TypeF32, TypeI32, TypeU32, u32 } from '../../../../../util/conversion.js';
+import { maxInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateBinaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+/** Generate set of max test cases from list of interesting values */
+function generateTestCases(values, makeCase) {
+ const cases = new Array();
+ values.forEach(e => {
+ values.forEach(f => {
+ cases.push(makeCase(e, f));
+ });
+ });
+ return cases;
+}
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('max', {
+ f32: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ maxInterval
+ );
+ },
+});
+
+g.test('abstract_int')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`abstract int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ return { input: [u32(x), u32(y)], expected: u32(Math.max(x, y)) };
+ };
+
+ const test_values = [0, 1, 2, 0x70000000, 0x80000000, 0xffffffff];
+ const cases = generateTestCases(test_values, makeCase);
+
+ await run(t, builtin('max'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ return { input: [i32(x), i32(y)], expected: i32(Math.max(x, y)) };
+ };
+
+ const test_values = [-0x70000000, -2, -1, 0, 1, 2, 0x70000000];
+ const cases = generateTestCases(test_values, makeCase);
+
+ await run(t, builtin('max'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('max'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js
new file mode 100644
index 0000000000..8316aff3d0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/min.spec.js
@@ -0,0 +1,108 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'min' builtin function
+
+S is AbstractInt, i32, or u32
+T is S or vecN<S>
+@const fn min(e1: T ,e2: T) -> T
+Returns e1 if e1 is less than e2, and e2 otherwise. Component-wise when T is a vector.
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn min(e1: T ,e2: T) -> T
+Returns e2 if e2 is less than e1, and e1 otherwise.
+If one operand is a NaN, the other is returned.
+If both operands are NaNs, a NaN is returned.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { i32, TypeF32, TypeI32, TypeU32, u32 } from '../../../../../util/conversion.js';
+import { minInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateBinaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('min', {
+ f32: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ minInterval
+ );
+ },
+});
+
+/** Generate set of min test cases from list of interesting values */
+function generateTestCases(values, makeCase) {
+ const cases = new Array();
+ values.forEach(e => {
+ values.forEach(f => {
+ cases.push(makeCase(e, f));
+ });
+ });
+ return cases;
+}
+
+g.test('abstract_int')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`abstract int tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ return { input: [u32(x), u32(y)], expected: u32(Math.min(x, y)) };
+ };
+
+ const test_values = [0, 1, 2, 0x70000000, 0x80000000, 0xffffffff];
+ const cases = generateTestCases(test_values, makeCase);
+
+ await run(t, builtin('min'), [TypeU32, TypeU32], TypeU32, t.params, cases);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ return { input: [i32(x), i32(y)], expected: i32(Math.min(x, y)) };
+ };
+
+ const test_values = [-0x70000000, -2, -1, 0, 1, 2, 0x70000000];
+ const cases = generateTestCases(test_values, makeCase);
+
+ await run(t, builtin('min'), [TypeI32, TypeI32], TypeI32, t.params, cases);
+ });
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('min'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js
new file mode 100644
index 0000000000..07e7642408
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/mix.spec.js
@@ -0,0 +1,88 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'mix' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn mix(e1: T, e2: T, e3: T) -> T
+Returns the linear blend of e1 and e2 (e.g. e1*(1-e3)+e2*e3). Component-wise when T is a vector.
+
+T is AbstractFloat, f32, or f16
+T2 is vecN<T>
+@const fn mix(e1: T2, e2: T2, e3: T) -> T2
+Returns the component-wise linear blend of e1 and e2, using scalar blending factor e3 for each component.
+Same as mix(e1,e2,T2(e3)).
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { mixIntervals } from '../../../../../util/f32_interval.js';
+import { sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateTernaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('mix', {
+ f32_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'f32-only',
+ ...mixIntervals
+ );
+ },
+ f32_non_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'unfiltered',
+ ...mixIntervals
+ );
+ },
+});
+
+g.test('matching_abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests with matching params`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('matching_f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 test with matching third param`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('mix'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('matching_f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests with matching third param`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('nonmatching_abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests with vector params and scalar third param`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('nonmatching_f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests with vector params and scalar third param`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('monmatching_f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests with vector params and scalar third param`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js
new file mode 100644
index 0000000000..710ee8dfa9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/modf.spec.js
@@ -0,0 +1,357 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'modf' builtin function
+
+T is f32 or f16
+@const fn modf(e:T) -> result_struct
+Splits |e| into fractional and whole number parts.
+The whole part is (|e| % 1.0), and the fractional part is |e| minus the whole part.
+Returns the result_struct for the given type.
+
+S is f32 or f16
+T is vecN<S>
+@const fn modf(e:T) -> result_struct
+Splits the components of |e| into fractional and whole number parts.
+The |i|'th component of the whole and fractional parts equal the whole and fractional parts of modf(e[i]).
+Returns the result_struct for the given type.
+
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { f32, toVector, TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { modfInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, quantizeToF32, vectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+/* @returns an ExpressionBuilder that evaluates modf and returns .whole from the result structure */
+function wholeBuilder() {
+ return value => `modf(${value}).whole`;
+}
+
+/* @returns an ExpressionBuilder that evaluates modf and returns .fract from the result structure */
+function fractBuilder() {
+ return value => `modf(${value}).fract`;
+}
+
+/* @returns a fract Case for a given vector input */
+function makeVectorCaseFract(v) {
+ v = v.map(quantizeToF32);
+ const fs = v.map(e => {
+ return modfInterval(e).fract;
+ });
+
+ return { input: toVector(v, f32), expected: fs };
+}
+
+/* @returns a fract Case for a given vector input */
+function makeVectorCaseWhole(v) {
+ v = v.map(quantizeToF32);
+ const ws = v.map(e => {
+ return modfInterval(e).whole;
+ });
+
+ return { input: toVector(v, f32), expected: ws };
+}
+
+export const d = makeCaseCache('modf', {
+ f32_fract: () => {
+ const makeCase = n => {
+ n = quantizeToF32(n);
+ return { input: f32(n), expected: modfInterval(n).fract };
+ };
+ return fullF32Range().map(makeCase);
+ },
+ f32_whole: () => {
+ const makeCase = n => {
+ n = quantizeToF32(n);
+ return { input: f32(n), expected: modfInterval(n).whole };
+ };
+ return fullF32Range().map(makeCase);
+ },
+ f32_vec2_fract: () => {
+ return vectorF32Range(2).map(makeVectorCaseFract);
+ },
+ f32_vec2_whole: () => {
+ return vectorF32Range(2).map(makeVectorCaseWhole);
+ },
+ f32_vec3_fract: () => {
+ return vectorF32Range(3).map(makeVectorCaseFract);
+ },
+ f32_vec3_whole: () => {
+ return vectorF32Range(3).map(makeVectorCaseWhole);
+ },
+ f32_vec4_fract: () => {
+ return vectorF32Range(4).map(makeVectorCaseFract);
+ },
+ f32_vec4_whole: () => {
+ return vectorF32Range(4).map(makeVectorCaseWhole);
+ },
+});
+
+g.test('f32_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is f32
+
+struct __modf_result_f32 {
+ fract : f32, // fractional part
+ whole : f32 // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_fract');
+ await run(t, fractBuilder(), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f32_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is f32
+
+struct __modf_result_f32 {
+ fract : f32, // fractional part
+ whole : f32 // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_whole');
+ await run(t, wholeBuilder(), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f32_vec2_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec2<f32>
+
+struct __modf_result_vec2_f32 {
+ fract : vec2<f32>, // fractional part
+ whole : vec2<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec2_fract');
+ await run(t, fractBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec2_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec2<f32>
+
+struct __modf_result_vec2_f32 {
+ fract : vec2<f32>, // fractional part
+ whole : vec2<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec2_whole');
+ await run(t, wholeBuilder(), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec3_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec3<f32>
+
+struct __modf_result_vec3_f32 {
+ fract : vec3<f32>, // fractional part
+ whole : vec3<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec3_fract');
+ await run(t, fractBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec3_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec3<f32>
+
+struct __modf_result_vec3_f32 {
+ fract : vec3<f32>, // fractional part
+ whole : vec3<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec3_whole');
+ await run(t, wholeBuilder(), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec4_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec4<f32>
+
+struct __modf_result_vec4_f32 {
+ fract : vec4<f32>, // fractional part
+ whole : vec4<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec4_fract');
+ await run(t, fractBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec4_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec4<f32>
+
+struct __modf_result_vec4_f32 {
+ fract : vec4<f32>, // fractional part
+ whole : vec4<f32> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get('f32_vec4_whole');
+ await run(t, wholeBuilder(), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases);
+ });
+
+g.test('f16_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is f16
+
+struct __modf_result_f16 {
+ fract : f16, // fractional part
+ whole : f16 // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is f16
+
+struct __modf_result_f16 {
+ fract : f16, // fractional part
+ whole : f16 // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec2_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec2<f16>
+
+struct __modf_result_vec2_f16 {
+ fract : vec2<f16>, // fractional part
+ whole : vec2<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec2_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec2<f16>
+
+struct __modf_result_vec2_f16 {
+ fract : vec2<f16>, // fractional part
+ whole : vec2<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec3_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec3<f16>
+
+struct __modf_result_vec3_f16 {
+ fract : vec3<f16>, // fractional part
+ whole : vec3<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec3_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec3<f16>
+
+struct __modf_result_vec3_f16 {
+ fract : vec3<f16>, // fractional part
+ whole : vec3<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec4_fract')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec4<f16>
+
+struct __modf_result_vec4_f16 {
+ fract : vec4<f16>, // fractional part
+ whole : vec4<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
+
+g.test('f16_vec4_whole')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+T is vec4<f16>
+
+struct __modf_result_vec4_f16 {
+ fract : vec4<f16>, // fractional part
+ whole : vec4<f16> // whole part
+}
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js
new file mode 100644
index 0000000000..f187ef9e93
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/normalize.spec.js
@@ -0,0 +1,89 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'normalize' builtin function
+
+T is AbstractFloat, f32, or f16
+@const fn normalize(e: vecN<T> ) -> vecN<T>
+Returns a unit vector in the same direction as e.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { normalizeInterval } from '../../../../../util/f32_interval.js';
+import { vectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateVectorToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('normalize', {
+ f32_vec2_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(2), 'f32-only', normalizeInterval);
+ },
+ f32_vec2_non_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(2), 'unfiltered', normalizeInterval);
+ },
+ f32_vec3_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(3), 'f32-only', normalizeInterval);
+ },
+ f32_vec3_non_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(3), 'unfiltered', normalizeInterval);
+ },
+ f32_vec4_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(4), 'f32-only', normalizeInterval);
+ },
+ f32_vec4_non_const: () => {
+ return generateVectorToVectorCases(vectorF32Range(4), 'unfiltered', normalizeInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(t, builtin('normalize'), [TypeVec(2, TypeF32)], TypeVec(2, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(t, builtin('normalize'), [TypeVec(3, TypeF32)], TypeVec(3, TypeF32), t.params, cases);
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(t, builtin('normalize'), [TypeVec(4, TypeF32)], TypeVec(4, TypeF32), t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js
new file mode 100644
index 0000000000..591a78eed2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16float.spec.js
@@ -0,0 +1,89 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Converts two floating point values to half-precision floating point numbers, and then combines them into one u32 value.
+Component e[i] of the input is converted to a IEEE-754 binary16 value,
+which is then placed in bits 16 × i through 16 × i + 15 of the result.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { anyOf, skipUndefined } from '../../../../../util/compare.js';
+import {
+ f32,
+ pack2x16float,
+ TypeF32,
+ TypeU32,
+ TypeVec,
+ u32,
+ vec2,
+} from '../../../../../util/conversion.js';
+import { cartesianProduct, fullF32Range, quantizeToF32 } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// pack2x16float has somewhat unusual behaviour, specifically around how it is
+// supposed to behave when values go OOB and when they are considered to have
+// gone OOB, so has its own bespoke implementation.
+
+/**
+ * @returns a Case for `pack2x16float`
+ * @param param0 first param for the case
+ * @param param1 second param for the case
+ * @param filter_undefined should inputs that cause an undefined expectation be
+ * filtered out, needed for const-eval
+ */
+function makeCase(param0, param1, filter_undefined) {
+ param0 = quantizeToF32(param0);
+ param1 = quantizeToF32(param1);
+
+ const results = pack2x16float(param0, param1);
+ if (filter_undefined && results.some(r => r === undefined)) {
+ return undefined;
+ }
+
+ return {
+ input: [vec2(f32(param0), f32(param1))],
+ expected: anyOf(
+ ...results.map(r => (r === undefined ? skipUndefined(undefined) : skipUndefined(u32(r))))
+ ),
+ };
+}
+
+/**
+ * @returns an array of Cases for `pack2x16float`
+ * @param param0s array of inputs to try for the first param
+ * @param param1s array of inputs to try for the second param
+ * @param filter_undefined should inputs that cause an undefined expectation be
+ * filtered out, needed for const-eval
+ */
+function generateCases(param0s, param1s, filter_undefined) {
+ return cartesianProduct(param0s, param1s)
+ .map(e => makeCase(e[0], e[1], filter_undefined))
+ .filter(c => c !== undefined);
+}
+
+export const d = makeCaseCache('pack2x16float', {
+ f32_const: () => {
+ return generateCases(fullF32Range(), fullF32Range(), true);
+ },
+ f32_non_const: () => {
+ return generateCases(fullF32Range(), fullF32Range(), false);
+ },
+});
+
+g.test('pack')
+ .specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions')
+ .desc(
+ `
+@const fn pack2x16float(e: vec2<f32>) -> u32
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('pack2x16float'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js
new file mode 100644
index 0000000000..7f6b72bb02
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16snorm.spec.js
@@ -0,0 +1,53 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Converts two normalized floating point values to 16-bit signed integers, and then combines them into one u32 value.
+Component e[i] of the input is converted to a 16-bit twos complement integer value
+⌊ 0.5 + 32767 × min(1, max(-1, e[i])) ⌋ which is then placed in
+bits 16 × i through 16 × i + 15 of the result.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import {
+ f32,
+ pack2x16snorm,
+ TypeF32,
+ TypeU32,
+ TypeVec,
+ u32,
+ vec2,
+} from '../../../../../util/conversion.js';
+import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('pack')
+ .specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions')
+ .desc(
+ `
+@const fn pack2x16snorm(e: vec2<f32>) -> u32
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ x = quantizeToF32(x);
+ y = quantizeToF32(y);
+ return { input: [vec2(f32(x), f32(y))], expected: u32(pack2x16snorm(x, y)) };
+ };
+
+ // Returns a value normalized to [-1, 1].
+ const normalizeF32 = n => {
+ return n / kValue.f32.positive.max;
+ };
+
+ const cases = vectorF32Range(2).flatMap(v => {
+ return [makeCase(...v), makeCase(...v.map(normalizeF32))];
+ });
+
+ await run(t, builtin('pack2x16snorm'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js
new file mode 100644
index 0000000000..5819c25618
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.js
@@ -0,0 +1,53 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Converts two normalized floating point values to 16-bit unsigned integers, and then combines them into one u32 value.
+Component e[i] of the input is converted to a 16-bit unsigned integer value
+⌊ 0.5 + 65535 × min(1, max(0, e[i])) ⌋ which is then placed in
+bits 16 × i through 16 × i + 15 of the result.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import {
+ f32,
+ pack2x16unorm,
+ TypeF32,
+ TypeU32,
+ TypeVec,
+ u32,
+ vec2,
+} from '../../../../../util/conversion.js';
+import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('pack')
+ .specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions')
+ .desc(
+ `
+@const fn pack2x16unorm(e: vec2<f32>) -> u32
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const makeCase = (x, y) => {
+ x = quantizeToF32(x);
+ y = quantizeToF32(y);
+ return { input: [vec2(f32(x), f32(y))], expected: u32(pack2x16unorm(x, y)) };
+ };
+
+ // Returns a value normalized to [0, 1].
+ const normalizeF32 = n => {
+ return n > 0 ? n / kValue.f32.positive.max : n / kValue.f32.negative.min;
+ };
+
+ const cases = vectorF32Range(2).flatMap(v => {
+ return [makeCase(...v), makeCase(...v.map(normalizeF32))];
+ });
+
+ await run(t, builtin('pack2x16unorm'), [TypeVec(2, TypeF32)], TypeU32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js
new file mode 100644
index 0000000000..f2696b8d6f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Converts four normalized floating point values to 8-bit signed integers, and then combines them into one u32 value.
+Component e[i] of the input is converted to an 8-bit twos complement integer value
+⌊ 0.5 + 127 × min(1, max(-1, e[i])) ⌋ which is then placed in
+bits 8 × i through 8 × i + 7 of the result.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import {
+ f32,
+ pack4x8snorm,
+ TypeF32,
+ TypeU32,
+ TypeVec,
+ u32,
+ vec4,
+} from '../../../../../util/conversion.js';
+import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('pack')
+ .specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions')
+ .desc(
+ `
+@const fn pack4x8snorm(e: vec4<f32>) -> u32
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const makeCase = vals => {
+ const vals_f32 = new Array(4);
+ for (const idx in vals) {
+ vals[idx] = quantizeToF32(vals[idx]);
+ vals_f32[idx] = f32(vals[idx]);
+ }
+
+ return { input: [vec4(...vals_f32)], expected: u32(pack4x8snorm(...vals)) };
+ };
+
+ // Returns a value normalized to [-1, 1].
+ const normalizeF32 = n => {
+ return n / kValue.f32.positive.max;
+ };
+
+ const cases = vectorF32Range(4).flatMap(v => {
+ return [makeCase(v), makeCase(v.map(normalizeF32))];
+ });
+
+ await run(t, builtin('pack4x8snorm'), [TypeVec(4, TypeF32)], TypeU32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js
new file mode 100644
index 0000000000..c12cf77944
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Converts four normalized floating point values to 8-bit unsigned integers, and then combines them into one u32 value.
+Component e[i] of the input is converted to an 8-bit unsigned integer value
+⌊ 0.5 + 255 × min(1, max(0, e[i])) ⌋ which is then placed in
+bits 8 × i through 8 × i + 7 of the result.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import {
+ f32,
+ pack4x8unorm,
+ TypeF32,
+ TypeU32,
+ TypeVec,
+ u32,
+ vec4,
+} from '../../../../../util/conversion.js';
+import { quantizeToF32, vectorF32Range } from '../../../../../util/math.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('pack')
+ .specURL('https://www.w3.org/TR/WGSL/#pack-builtin-functions')
+ .desc(
+ `
+@const fn pack4x8unorm(e: vec4<f32>) -> u32
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const makeCase = vals => {
+ const vals_f32 = new Array(4);
+ for (const idx in vals) {
+ vals[idx] = quantizeToF32(vals[idx]);
+ vals_f32[idx] = f32(vals[idx]);
+ }
+
+ return { input: [vec4(...vals_f32)], expected: u32(pack4x8unorm(...vals)) };
+ };
+
+ // Returns a value normalized to [0, 1].
+ const normalizeF32 = n => {
+ return n > 0 ? n / kValue.f32.positive.max : n / kValue.f32.negative.min;
+ };
+
+ const cases = vectorF32Range(4).flatMap(v => {
+ return [makeCase(v), makeCase(v.map(normalizeF32))];
+ });
+
+ await run(t, builtin('pack4x8unorm'), [TypeVec(4, TypeF32)], TypeU32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js
new file mode 100644
index 0000000000..76f37f1931
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/pow.spec.js
@@ -0,0 +1,61 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'pow' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn pow(e1: T ,e2: T ) -> T
+Returns e1 raised to the power e2. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { powInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateBinaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('pow', {
+ f32_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'f32-only',
+ powInterval
+ );
+ },
+ f32_non_const: () => {
+ return generateBinaryToF32IntervalCases(
+ fullF32Range(),
+ fullF32Range(),
+ 'unfiltered',
+ powInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('pow'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js
new file mode 100644
index 0000000000..3fb381f3a6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/quantizeToF16.spec.js
@@ -0,0 +1,71 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'quantizeToF16' builtin function
+
+T is f32 or vecN<f32>
+@const fn quantizeToF16(e: T ) -> T
+Quantizes a 32-bit floating point value e as if e were converted to a IEEE 754
+binary16 value, and then converted back to a IEEE 754 binary32 value.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { kValue } from '../../../../../util/constants.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { quantizeToF16Interval } from '../../../../../util/f32_interval.js';
+import { fullF16Range, fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('quantizeToF16', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ kValue.f16.negative.min,
+ kValue.f16.negative.max,
+ kValue.f16.subnormal.negative.min,
+ kValue.f16.subnormal.negative.max,
+ kValue.f16.subnormal.positive.min,
+ kValue.f16.subnormal.positive.max,
+ kValue.f16.positive.min,
+ kValue.f16.positive.max,
+ ...fullF16Range(),
+ ],
+
+ 'f32-only',
+ quantizeToF16Interval
+ );
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ kValue.f16.negative.min,
+ kValue.f16.negative.max,
+ kValue.f16.subnormal.negative.min,
+ kValue.f16.subnormal.negative.max,
+ kValue.f16.subnormal.positive.min,
+ kValue.f16.subnormal.positive.max,
+ kValue.f16.positive.min,
+ kValue.f16.positive.max,
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ quantizeToF16Interval
+ );
+ },
+});
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('quantizeToF16'), [TypeF32], TypeF32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js
new file mode 100644
index 0000000000..eb4d52efbf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/radians.spec.js
@@ -0,0 +1,49 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'radians' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn radians(e1: T ) -> T
+Converts degrees to radians, approximating e1 * π / 180.
+Component-wise when T is a vector
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { radiansInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('radians', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', radiansInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('radians'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js
new file mode 100644
index 0000000000..233fd8418e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reflect.spec.js
@@ -0,0 +1,141 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'reflect' builtin function
+
+T is vecN<AbstractFloat>, vecN<f32>, or vecN<f16>
+@const fn reflect(e1: T, e2: T ) -> T
+For the incident vector e1 and surface orientation e2, returns the reflection
+direction e1-2*dot(e2,e1)*e2.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeVec } from '../../../../../util/conversion.js';
+import { reflectInterval } from '../../../../../util/f32_interval.js';
+import { sparseVectorF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateVectorPairToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('reflect', {
+ f32_vec2_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'f32-only',
+ reflectInterval
+ );
+ },
+ f32_vec2_non_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ 'unfiltered',
+ reflectInterval
+ );
+ },
+ f32_vec3_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'f32-only',
+ reflectInterval
+ );
+ },
+ f32_vec3_non_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ 'unfiltered',
+ reflectInterval
+ );
+ },
+ f32_vec4_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'f32-only',
+ reflectInterval
+ );
+ },
+ f32_vec4_non_const: () => {
+ return generateVectorPairToVectorCases(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ 'unfiltered',
+ reflectInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(
+ t,
+ builtin('reflect'),
+ [TypeVec(2, TypeF32), TypeVec(2, TypeF32)],
+ TypeVec(2, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(
+ t,
+ builtin('reflect'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32)],
+ TypeVec(3, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(
+ t,
+ builtin('reflect'),
+ [TypeVec(4, TypeF32), TypeVec(4, TypeF32)],
+ TypeVec(4, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js
new file mode 100644
index 0000000000..7fbc7d3fd8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/refract.spec.js
@@ -0,0 +1,195 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'refract' builtin function
+
+T is vecN<I>
+I is AbstractFloat, f32, or f16
+@const fn refract(e1: T ,e2: T ,e3: I ) -> T
+For the incident vector e1 and surface normal e2, and the ratio of indices of
+refraction e3, let k = 1.0 -e3*e3* (1.0 - dot(e2,e1) * dot(e2,e1)).
+If k < 0.0, returns the refraction vector 0.0, otherwise return the refraction
+vector e3*e1- (e3* dot(e2,e1) + sqrt(k)) *e2.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { f32, TypeF32, TypeVec, Vector } from '../../../../../util/conversion.js';
+import { refractInterval } from '../../../../../util/f32_interval.js';
+import { sparseVectorF32Range, quantizeToF32, sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// Using a bespoke implementation of make*Case and generate*Cases here
+// since refract is the only builtin with the API signature
+// (vec, vec, scalar) -> vec
+
+/**
+ * @returns a Case for `refract`
+ * @param i the `i` param for the case
+ * @param s the `s` param for the case
+ * @param r the `r` param for the case
+ * @param check what interval checking to apply
+ * */
+function makeCaseF32(i, s, r, check) {
+ i = i.map(quantizeToF32);
+ s = s.map(quantizeToF32);
+ r = quantizeToF32(r);
+
+ const i_f32 = i.map(f32);
+ const s_f32 = s.map(f32);
+ const r_f32 = f32(r);
+
+ const vectors = refractInterval(i, s, r);
+ if (check === 'f32-only' && vectors.some(e => !e.isFinite())) {
+ return undefined;
+ }
+
+ return {
+ input: [new Vector(i_f32), new Vector(s_f32), r_f32],
+ expected: refractInterval(i, s, r),
+ };
+}
+
+/**
+ * @returns an array of Cases for `refract`
+ * @param param_is array of inputs to try for the `i` param
+ * @param param_ss array of inputs to try for the `s` param
+ * @param param_rs array of inputs to try for the `r` param
+ * @param check what interval checking to apply
+ */
+function generateCasesF32(param_is, param_ss, param_rs, check) {
+ // Cannot use `cartesianProduct` here due to heterogeneous param types
+ return param_is
+ .flatMap(i => {
+ return param_ss.flatMap(s => {
+ return param_rs.map(r => {
+ return makeCaseF32(i, s, r, check);
+ });
+ });
+ })
+ .filter(c => c !== undefined);
+}
+
+export const d = makeCaseCache('refract', {
+ f32_vec2_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ sparseF32Range(),
+ 'f32-only'
+ );
+ },
+ f32_vec2_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(2),
+ sparseVectorF32Range(2),
+ sparseF32Range(),
+ 'unfiltered'
+ );
+ },
+ f32_vec3_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ sparseF32Range(),
+ 'f32-only'
+ );
+ },
+ f32_vec3_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(3),
+ sparseVectorF32Range(3),
+ sparseF32Range(),
+ 'unfiltered'
+ );
+ },
+ f32_vec4_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ sparseF32Range(),
+ 'f32-only'
+ );
+ },
+ f32_vec4_non_const: () => {
+ return generateCasesF32(
+ sparseVectorF32Range(4),
+ sparseVectorF32Range(4),
+ sparseF32Range(),
+ 'unfiltered'
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
+
+g.test('f32_vec2')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec2s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec2_const' : 'f32_vec2_non_const'
+ );
+
+ await run(
+ t,
+ builtin('refract'),
+ [TypeVec(2, TypeF32), TypeVec(2, TypeF32), TypeF32],
+ TypeVec(2, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec3')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec3s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec3_const' : 'f32_vec3_non_const'
+ );
+
+ await run(
+ t,
+ builtin('refract'),
+ [TypeVec(3, TypeF32), TypeVec(3, TypeF32), TypeF32],
+ TypeVec(3, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f32_vec4')
+ .specURL('https://www.w3.org/TR/WGSL/#numeric-builtin-functions')
+ .desc(`f32 tests using vec4s`)
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(
+ t.params.inputSource === 'const' ? 'f32_vec4_const' : 'f32_vec4_non_const'
+ );
+
+ await run(
+ t,
+ builtin('refract'),
+ [TypeVec(4, TypeF32), TypeVec(4, TypeF32), TypeF32],
+ TypeVec(4, TypeF32),
+ t.params,
+ cases
+ );
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js
new file mode 100644
index 0000000000..41f72419df
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/reverseBits.spec.js
@@ -0,0 +1,811 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'reversBits' builtin function
+
+S is i32, u32
+T is S or vecN<S>
+@const fn reverseBits(e: T ) -> T
+Reverses the bits in e: The bit at position k of the result equals the bit at position 31-k of e.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeU32, u32Bits, TypeI32, i32Bits } from '../../../../../util/conversion.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('u32')
+ .specURL('https://www.w3.org/TR/WGSL/#integer-builtin-functions')
+ .desc(`u32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+
+ await run(t, builtin('reverseBits'), [TypeU32], TypeU32, cfg, [
+ // Zero
+ {
+ input: u32Bits(0b00000000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000000000),
+ },
+
+ // One
+ {
+ input: u32Bits(0b00000000000000000000000000000001),
+ expected: u32Bits(0b10000000000000000000000000000000),
+ },
+
+ // 0's after leading 1
+ {
+ input: u32Bits(0b00000000000000000000000000000010),
+ expected: u32Bits(0b01000000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000000100),
+ expected: u32Bits(0b00100000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000001000),
+ expected: u32Bits(0b00010000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000010000),
+ expected: u32Bits(0b00001000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000100000),
+ expected: u32Bits(0b00000100000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000001000000),
+ expected: u32Bits(0b00000010000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000010000000),
+ expected: u32Bits(0b00000001000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000100000000),
+ expected: u32Bits(0b00000000100000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000001000000000),
+ expected: u32Bits(0b00000000010000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000010000000000),
+ expected: u32Bits(0b00000000001000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000100000000000),
+ expected: u32Bits(0b00000000000100000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000001000000000000),
+ expected: u32Bits(0b00000000000010000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000010000000000000),
+ expected: u32Bits(0b00000000000001000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000100000000000000),
+ expected: u32Bits(0b00000000000000100000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000001000000000000000),
+ expected: u32Bits(0b00000000000000010000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000010000000000000000),
+ expected: u32Bits(0b00000000000000001000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000100000000000000000),
+ expected: u32Bits(0b00000000000000000100000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000001000000000000000000),
+ expected: u32Bits(0b00000000000000000010000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000010000000000000000000),
+ expected: u32Bits(0b00000000000000000001000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000100000000000000000000),
+ expected: u32Bits(0b00000000000000000000100000000000),
+ },
+ {
+ input: u32Bits(0b00000000001000000000000000000000),
+ expected: u32Bits(0b00000000000000000000010000000000),
+ },
+ {
+ input: u32Bits(0b00000000010000000000000000000000),
+ expected: u32Bits(0b00000000000000000000001000000000),
+ },
+ {
+ input: u32Bits(0b00000000100000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000100000000),
+ },
+ {
+ input: u32Bits(0b00000001000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000010000000),
+ },
+ {
+ input: u32Bits(0b00000010000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000001000000),
+ },
+ {
+ input: u32Bits(0b00000100000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000100000),
+ },
+ {
+ input: u32Bits(0b00001000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000010000),
+ },
+ {
+ input: u32Bits(0b00010000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000001000),
+ },
+ {
+ input: u32Bits(0b00100000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000000100),
+ },
+ {
+ input: u32Bits(0b01000000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000000010),
+ },
+ {
+ input: u32Bits(0b10000000000000000000000000000000),
+ expected: u32Bits(0b00000000000000000000000000000001),
+ },
+
+ // 1's after leading 1
+ {
+ input: u32Bits(0b00000000000000000000000000000011),
+ expected: u32Bits(0b11000000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000000111),
+ expected: u32Bits(0b11100000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000001111),
+ expected: u32Bits(0b11110000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000011111),
+ expected: u32Bits(0b11111000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000111111),
+ expected: u32Bits(0b11111100000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000001111111),
+ expected: u32Bits(0b11111110000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000011111111),
+ expected: u32Bits(0b11111111000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000111111111),
+ expected: u32Bits(0b11111111100000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000001111111111),
+ expected: u32Bits(0b11111111110000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000011111111111),
+ expected: u32Bits(0b11111111111000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000111111111111),
+ expected: u32Bits(0b11111111111100000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000001111111111111),
+ expected: u32Bits(0b11111111111110000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000011111111111111),
+ expected: u32Bits(0b11111111111111000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000111111111111111),
+ expected: u32Bits(0b11111111111111100000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000001111111111111111),
+ expected: u32Bits(0b11111111111111110000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000011111111111111111),
+ expected: u32Bits(0b11111111111111111000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000111111111111111111),
+ expected: u32Bits(0b11111111111111111100000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000001111111111111111111),
+ expected: u32Bits(0b11111111111111111110000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000011111111111111111111),
+ expected: u32Bits(0b11111111111111111111000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000111111111111111111111),
+ expected: u32Bits(0b11111111111111111111100000000000),
+ },
+ {
+ input: u32Bits(0b00000000001111111111111111111111),
+ expected: u32Bits(0b11111111111111111111110000000000),
+ },
+ {
+ input: u32Bits(0b00000000011111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111000000000),
+ },
+ {
+ input: u32Bits(0b00000000111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111100000000),
+ },
+ {
+ input: u32Bits(0b00000001111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111110000000),
+ },
+ {
+ input: u32Bits(0b00000011111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111000000),
+ },
+ {
+ input: u32Bits(0b00000111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111100000),
+ },
+ {
+ input: u32Bits(0b00001111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111110000),
+ },
+ {
+ input: u32Bits(0b00011111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111111000),
+ },
+ {
+ input: u32Bits(0b00111111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111111100),
+ },
+ {
+ input: u32Bits(0b01111111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111111110),
+ },
+ {
+ input: u32Bits(0b11111111111111111111111111111111),
+ expected: u32Bits(0b11111111111111111111111111111111),
+ },
+
+ // random after leading 1
+ {
+ input: u32Bits(0b00000000000000000000000000000110),
+ expected: u32Bits(0b01100000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000001101),
+ expected: u32Bits(0b10110000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000011101),
+ expected: u32Bits(0b10111000000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000000111001),
+ expected: u32Bits(0b10011100000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000001101111),
+ expected: u32Bits(0b11110110000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000011111111),
+ expected: u32Bits(0b11111111000000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000000111101111),
+ expected: u32Bits(0b11110111100000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000001111111111),
+ expected: u32Bits(0b11111111110000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000011111110001),
+ expected: u32Bits(0b10001111111000000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000000111011011101),
+ expected: u32Bits(0b10111011011100000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000001101101111111),
+ expected: u32Bits(0b11111110110110000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000011111111011111),
+ expected: u32Bits(0b11111011111111000000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000000101111001110101),
+ expected: u32Bits(0b10101110011110100000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000001101111011110111),
+ expected: u32Bits(0b11101111011110110000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000011111111111110011),
+ expected: u32Bits(0b11001111111111111000000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000000111111111110111111),
+ expected: u32Bits(0b11111101111111111100000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000001111111011111111111),
+ expected: u32Bits(0b11111111111011111110000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000011111111111111111111),
+ expected: u32Bits(0b11111111111111111111000000000000),
+ },
+ {
+ input: u32Bits(0b00000000000111110101011110111111),
+ expected: u32Bits(0b11111101111010101111100000000000),
+ },
+ {
+ input: u32Bits(0b00000000001111101111111111110111),
+ expected: u32Bits(0b11101111111111110111110000000000),
+ },
+ {
+ input: u32Bits(0b00000000011111111111010000101111),
+ expected: u32Bits(0b11110100001011111111111000000000),
+ },
+ {
+ input: u32Bits(0b00000000111111111111001111111011),
+ expected: u32Bits(0b11011111110011111111111100000000),
+ },
+ {
+ input: u32Bits(0b00000001111111011111101111111111),
+ expected: u32Bits(0b11111111110111111011111110000000),
+ },
+ {
+ input: u32Bits(0b00000011101011111011110111111011),
+ expected: u32Bits(0b11011111101111011111010111000000),
+ },
+ {
+ input: u32Bits(0b00000111111110111111111111111111),
+ expected: u32Bits(0b11111111111111111101111111100000),
+ },
+ {
+ input: u32Bits(0b00001111000000011011011110111111),
+ expected: u32Bits(0b11111101111011011000000011110000),
+ },
+ {
+ input: u32Bits(0b00011110101111011111111111111111),
+ expected: u32Bits(0b11111111111111111011110101111000),
+ },
+ {
+ input: u32Bits(0b00110110111111100111111110111101),
+ expected: u32Bits(0b10111101111111100111111101101100),
+ },
+ {
+ input: u32Bits(0b01010111111101111111011111011111),
+ expected: u32Bits(0b11111011111011111110111111101010),
+ },
+ {
+ input: u32Bits(0b11100010011110101101101110101111),
+ expected: u32Bits(0b11110101110110110101111001000111),
+ },
+ ]);
+ });
+
+g.test('i32')
+ .specURL('https://www.w3.org/TR/2021/WD-WGSL-20210929/#integer-builtin-functions')
+ .desc(`i32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cfg = t.params;
+
+ await run(t, builtin('reverseBits'), [TypeI32], TypeI32, cfg, [
+ // Zero
+ {
+ input: i32Bits(0b00000000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000000000),
+ },
+
+ // One
+ {
+ input: i32Bits(0b00000000000000000000000000000001),
+ expected: i32Bits(0b10000000000000000000000000000000),
+ },
+
+ // 0's after leading 1
+ {
+ input: i32Bits(0b00000000000000000000000000000010),
+ expected: i32Bits(0b01000000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000000100),
+ expected: i32Bits(0b00100000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000001000),
+ expected: i32Bits(0b00010000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000010000),
+ expected: i32Bits(0b00001000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000100000),
+ expected: i32Bits(0b00000100000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000001000000),
+ expected: i32Bits(0b00000010000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000010000000),
+ expected: i32Bits(0b00000001000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000100000000),
+ expected: i32Bits(0b00000000100000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000001000000000),
+ expected: i32Bits(0b00000000010000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000010000000000),
+ expected: i32Bits(0b00000000001000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000100000000000),
+ expected: i32Bits(0b00000000000100000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000001000000000000),
+ expected: i32Bits(0b00000000000010000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000010000000000000),
+ expected: i32Bits(0b00000000000001000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000100000000000000),
+ expected: i32Bits(0b00000000000000100000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000001000000000000000),
+ expected: i32Bits(0b00000000000000010000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000010000000000000000),
+ expected: i32Bits(0b00000000000000001000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000100000000000000000),
+ expected: i32Bits(0b00000000000000000100000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000001000000000000000000),
+ expected: i32Bits(0b00000000000000000010000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000010000000000000000000),
+ expected: i32Bits(0b00000000000000000001000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000100000000000000000000),
+ expected: i32Bits(0b00000000000000000000100000000000),
+ },
+ {
+ input: i32Bits(0b00000000001000000000000000000000),
+ expected: i32Bits(0b00000000000000000000010000000000),
+ },
+ {
+ input: i32Bits(0b00000000010000000000000000000000),
+ expected: i32Bits(0b00000000000000000000001000000000),
+ },
+ {
+ input: i32Bits(0b00000000100000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000100000000),
+ },
+ {
+ input: i32Bits(0b00000001000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000010000000),
+ },
+ {
+ input: i32Bits(0b00000010000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000001000000),
+ },
+ {
+ input: i32Bits(0b00000100000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000100000),
+ },
+ {
+ input: i32Bits(0b00001000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000010000),
+ },
+ {
+ input: i32Bits(0b00010000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000001000),
+ },
+ {
+ input: i32Bits(0b00100000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000000100),
+ },
+ {
+ input: i32Bits(0b01000000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000000010),
+ },
+ {
+ input: i32Bits(0b10000000000000000000000000000000),
+ expected: i32Bits(0b00000000000000000000000000000001),
+ },
+
+ // 1's after leading 1
+ {
+ input: i32Bits(0b00000000000000000000000000000011),
+ expected: i32Bits(0b11000000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000000111),
+ expected: i32Bits(0b11100000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000001111),
+ expected: i32Bits(0b11110000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000011111),
+ expected: i32Bits(0b11111000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000111111),
+ expected: i32Bits(0b11111100000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000001111111),
+ expected: i32Bits(0b11111110000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000011111111),
+ expected: i32Bits(0b11111111000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000111111111),
+ expected: i32Bits(0b11111111100000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000001111111111),
+ expected: i32Bits(0b11111111110000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000011111111111),
+ expected: i32Bits(0b11111111111000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000111111111111),
+ expected: i32Bits(0b11111111111100000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000001111111111111),
+ expected: i32Bits(0b11111111111110000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000011111111111111),
+ expected: i32Bits(0b11111111111111000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000111111111111111),
+ expected: i32Bits(0b11111111111111100000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000001111111111111111),
+ expected: i32Bits(0b11111111111111110000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000011111111111111111),
+ expected: i32Bits(0b11111111111111111000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000111111111111111111),
+ expected: i32Bits(0b11111111111111111100000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000001111111111111111111),
+ expected: i32Bits(0b11111111111111111110000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000011111111111111111111),
+ expected: i32Bits(0b11111111111111111111000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000111111111111111111111),
+ expected: i32Bits(0b11111111111111111111100000000000),
+ },
+ {
+ input: i32Bits(0b00000000001111111111111111111111),
+ expected: i32Bits(0b11111111111111111111110000000000),
+ },
+ {
+ input: i32Bits(0b00000000011111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111000000000),
+ },
+ {
+ input: i32Bits(0b00000000111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111100000000),
+ },
+ {
+ input: i32Bits(0b00000001111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111110000000),
+ },
+ {
+ input: i32Bits(0b00000011111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111000000),
+ },
+ {
+ input: i32Bits(0b00000111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111100000),
+ },
+ {
+ input: i32Bits(0b00001111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111110000),
+ },
+ {
+ input: i32Bits(0b00011111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111111000),
+ },
+ {
+ input: i32Bits(0b00111111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111111100),
+ },
+ {
+ input: i32Bits(0b01111111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111111110),
+ },
+ {
+ input: i32Bits(0b11111111111111111111111111111111),
+ expected: i32Bits(0b11111111111111111111111111111111),
+ },
+
+ // random after leading 1
+ {
+ input: i32Bits(0b00000000000000000000000000000110),
+ expected: i32Bits(0b01100000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000001101),
+ expected: i32Bits(0b10110000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000011101),
+ expected: i32Bits(0b10111000000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000000111001),
+ expected: i32Bits(0b10011100000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000001101111),
+ expected: i32Bits(0b11110110000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000011111111),
+ expected: i32Bits(0b11111111000000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000000111101111),
+ expected: i32Bits(0b11110111100000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000001111111111),
+ expected: i32Bits(0b11111111110000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000011111110001),
+ expected: i32Bits(0b10001111111000000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000000111011011101),
+ expected: i32Bits(0b10111011011100000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000001101101111111),
+ expected: i32Bits(0b11111110110110000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000011111111011111),
+ expected: i32Bits(0b11111011111111000000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000000101111001110101),
+ expected: i32Bits(0b10101110011110100000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000001101111011110111),
+ expected: i32Bits(0b11101111011110110000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000011111111111110011),
+ expected: i32Bits(0b11001111111111111000000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000000111111111110111111),
+ expected: i32Bits(0b11111101111111111100000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000001111111011111111111),
+ expected: i32Bits(0b11111111111011111110000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000011111111111111111111),
+ expected: i32Bits(0b11111111111111111111000000000000),
+ },
+ {
+ input: i32Bits(0b00000000000111110101011110111111),
+ expected: i32Bits(0b11111101111010101111100000000000),
+ },
+ {
+ input: i32Bits(0b00000000001111101111111111110111),
+ expected: i32Bits(0b11101111111111110111110000000000),
+ },
+ {
+ input: i32Bits(0b00000000011111111111010000101111),
+ expected: i32Bits(0b11110100001011111111111000000000),
+ },
+ {
+ input: i32Bits(0b00000000111111111111001111111011),
+ expected: i32Bits(0b11011111110011111111111100000000),
+ },
+ {
+ input: i32Bits(0b00000001111111011111101111111111),
+ expected: i32Bits(0b11111111110111111011111110000000),
+ },
+ {
+ input: i32Bits(0b00000011101011111011110111111011),
+ expected: i32Bits(0b11011111101111011111010111000000),
+ },
+ {
+ input: i32Bits(0b00000111111110111111111111111111),
+ expected: i32Bits(0b11111111111111111101111111100000),
+ },
+ {
+ input: i32Bits(0b00001111000000011011011110111111),
+ expected: i32Bits(0b11111101111011011000000011110000),
+ },
+ {
+ input: i32Bits(0b00011110101111011111111111111111),
+ expected: i32Bits(0b11111111111111111011110101111000),
+ },
+ {
+ input: i32Bits(0b00110110111111100111111110111101),
+ expected: i32Bits(0b10111101111111100111111101101100),
+ },
+ {
+ input: i32Bits(0b01010111111101111111011111011111),
+ expected: i32Bits(0b11111011111011111110111111101010),
+ },
+ {
+ input: i32Bits(0b11100010011110101101101110101111),
+ expected: i32Bits(0b11110101110110110101111001000111),
+ },
+ ]);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js
new file mode 100644
index 0000000000..1282eb21ce
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/round.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'round' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn round(e: T) -> T
+Result is the integer k nearest to e, as a floating point value.
+When e lies halfway between integers k and k+1, the result is k when k is even,
+and k+1 when k is odd.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { roundInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('round', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', roundInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('round'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js
new file mode 100644
index 0000000000..e7290fa7d8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/saturate.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'saturate' builtin function
+
+S is AbstractFloat, f32, or f16
+T is S or vecN<S>
+@const fn saturate(e: T) -> T
+Returns clamp(e, 0.0, 1.0). Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { saturateInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('saturate', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Non-clamped values
+ ...linearRange(0.0, 1.0, 100),
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ saturateInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('saturate'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js
new file mode 100644
index 0000000000..9f86a28526
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/select.spec.js
@@ -0,0 +1,227 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'select' builtin function
+
+T is scalar, abstract numeric type, or vector
+@const fn select(f: T, t: T, cond: bool) -> T
+Returns t when cond is true, and f otherwise.
+
+T is scalar or abstract numeric type
+@const fn select(f: vecN<T>, t: vecN<T>, cond: vecN<bool>) -> vecN<T>
+Component-wise selection. Result component i is evaluated as select(f[i],t[i],cond[i]).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import {
+ TypeVec,
+ TypeBool,
+ TypeF32,
+ TypeI32,
+ TypeU32,
+ f32,
+ i32,
+ u32,
+ False,
+ True,
+ bool,
+ vec2,
+ vec3,
+ vec4,
+} from '../../../../../util/conversion.js';
+import { run, allInputSources } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+function makeBool(n) {
+ return bool((n & 1) === 1);
+}
+
+const dataType = {
+ b: {
+ type: TypeBool,
+ constructor: makeBool,
+ },
+ f: {
+ type: TypeF32,
+ constructor: f32,
+ },
+ i: {
+ type: TypeI32,
+ constructor: i32,
+ },
+ u: {
+ type: TypeU32,
+ constructor: u32,
+ },
+};
+
+g.test('scalar')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-builtin-functions')
+ .desc(`scalar tests`)
+ .params(u =>
+ u
+ .combine('inputSource', allInputSources)
+ .combine('component', ['b', 'f', 'i', 'u'])
+ .combine('overload', ['scalar', 'vec2', 'vec3', 'vec4'])
+ )
+ .fn(async t => {
+ const componentType = dataType[t.params.component].type;
+ const cons = dataType[t.params.component].constructor;
+
+ // Create the scalar values that will be selected from, either as scalars
+ // or vectors.
+ //
+ // Each boolean will select between c[k] and c[k+4]. Those values must
+ // always compare as different. The tricky case is boolean, where the parity
+ // has to be different, i.e. c[k]-c[k+4] must be odd.
+ const c = [0, 1, 2, 3, 5, 6, 7, 8].map(i => cons(i));
+ // Now form vectors that will have different components from each other.
+ const v2a = vec2(c[0], c[1]);
+ const v2b = vec2(c[4], c[5]);
+ const v3a = vec3(c[0], c[1], c[2]);
+ const v3b = vec3(c[4], c[5], c[6]);
+ const v4a = vec4(c[0], c[1], c[2], c[3]);
+ const v4b = vec4(c[4], c[5], c[6], c[7]);
+
+ const overloads = {
+ scalar: {
+ type: componentType,
+ cases: [
+ { input: [c[0], c[1], False], expected: c[0] },
+ { input: [c[0], c[1], True], expected: c[1] },
+ ],
+ },
+ vec2: {
+ type: TypeVec(2, componentType),
+ cases: [
+ { input: [v2a, v2b, False], expected: v2a },
+ { input: [v2a, v2b, True], expected: v2b },
+ ],
+ },
+ vec3: {
+ type: TypeVec(3, componentType),
+ cases: [
+ { input: [v3a, v3b, False], expected: v3a },
+ { input: [v3a, v3b, True], expected: v3b },
+ ],
+ },
+ vec4: {
+ type: TypeVec(4, componentType),
+ cases: [
+ { input: [v4a, v4b, False], expected: v4a },
+ { input: [v4a, v4b, True], expected: v4b },
+ ],
+ },
+ };
+ const overload = overloads[t.params.overload];
+
+ await run(
+ t,
+ builtin('select'),
+ [overload.type, overload.type, TypeBool],
+ overload.type,
+ t.params,
+ overload.cases
+ );
+ });
+
+g.test('vector')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-builtin-functions')
+ .desc(`vector tests`)
+ .params(u =>
+ u
+ .combine('inputSource', allInputSources)
+ .combine('component', ['b', 'f', 'i', 'u'])
+ .combine('overload', ['vec2', 'vec3', 'vec4'])
+ )
+ .fn(async t => {
+ const componentType = dataType[t.params.component].type;
+ const cons = dataType[t.params.component].constructor;
+
+ // Create the scalar values that will be selected from.
+ //
+ // Each boolean will select between c[k] and c[k+4]. Those values must
+ // always compare as different. The tricky case is boolean, where the parity
+ // has to be different, i.e. c[k]-c[k+4] must be odd.
+ const c = [0, 1, 2, 3, 5, 6, 7, 8].map(i => cons(i));
+ const T = True;
+ const F = False;
+
+ let tests;
+
+ switch (t.params.overload) {
+ case 'vec2': {
+ const a = vec2(c[0], c[1]);
+ const b = vec2(c[4], c[5]);
+ tests = {
+ dataType: TypeVec(2, componentType),
+ boolType: TypeVec(2, TypeBool),
+ cases: [
+ { input: [a, b, vec2(F, F)], expected: vec2(a.x, a.y) },
+ { input: [a, b, vec2(F, T)], expected: vec2(a.x, b.y) },
+ { input: [a, b, vec2(T, F)], expected: vec2(b.x, a.y) },
+ { input: [a, b, vec2(T, T)], expected: vec2(b.x, b.y) },
+ ],
+ };
+ break;
+ }
+ case 'vec3': {
+ const a = vec3(c[0], c[1], c[2]);
+ const b = vec3(c[4], c[5], c[6]);
+ tests = {
+ dataType: TypeVec(3, componentType),
+ boolType: TypeVec(3, TypeBool),
+ cases: [
+ { input: [a, b, vec3(F, F, F)], expected: vec3(a.x, a.y, a.z) },
+ { input: [a, b, vec3(F, F, T)], expected: vec3(a.x, a.y, b.z) },
+ { input: [a, b, vec3(F, T, F)], expected: vec3(a.x, b.y, a.z) },
+ { input: [a, b, vec3(F, T, T)], expected: vec3(a.x, b.y, b.z) },
+ { input: [a, b, vec3(T, F, F)], expected: vec3(b.x, a.y, a.z) },
+ { input: [a, b, vec3(T, F, T)], expected: vec3(b.x, a.y, b.z) },
+ { input: [a, b, vec3(T, T, F)], expected: vec3(b.x, b.y, a.z) },
+ { input: [a, b, vec3(T, T, T)], expected: vec3(b.x, b.y, b.z) },
+ ],
+ };
+ break;
+ }
+ case 'vec4': {
+ const a = vec4(c[0], c[1], c[2], c[3]);
+ const b = vec4(c[4], c[5], c[6], c[7]);
+ tests = {
+ dataType: TypeVec(4, componentType),
+ boolType: TypeVec(4, TypeBool),
+ cases: [
+ { input: [a, b, vec4(F, F, F, F)], expected: vec4(a.x, a.y, a.z, a.w) },
+ { input: [a, b, vec4(F, F, F, T)], expected: vec4(a.x, a.y, a.z, b.w) },
+ { input: [a, b, vec4(F, F, T, F)], expected: vec4(a.x, a.y, b.z, a.w) },
+ { input: [a, b, vec4(F, F, T, T)], expected: vec4(a.x, a.y, b.z, b.w) },
+ { input: [a, b, vec4(F, T, F, F)], expected: vec4(a.x, b.y, a.z, a.w) },
+ { input: [a, b, vec4(F, T, F, T)], expected: vec4(a.x, b.y, a.z, b.w) },
+ { input: [a, b, vec4(F, T, T, F)], expected: vec4(a.x, b.y, b.z, a.w) },
+ { input: [a, b, vec4(F, T, T, T)], expected: vec4(a.x, b.y, b.z, b.w) },
+ { input: [a, b, vec4(T, F, F, F)], expected: vec4(b.x, a.y, a.z, a.w) },
+ { input: [a, b, vec4(T, F, F, T)], expected: vec4(b.x, a.y, a.z, b.w) },
+ { input: [a, b, vec4(T, F, T, F)], expected: vec4(b.x, a.y, b.z, a.w) },
+ { input: [a, b, vec4(T, F, T, T)], expected: vec4(b.x, a.y, b.z, b.w) },
+ { input: [a, b, vec4(T, T, F, F)], expected: vec4(b.x, b.y, a.z, a.w) },
+ { input: [a, b, vec4(T, T, F, T)], expected: vec4(b.x, b.y, a.z, b.w) },
+ { input: [a, b, vec4(T, T, T, F)], expected: vec4(b.x, b.y, b.z, a.w) },
+ { input: [a, b, vec4(T, T, T, T)], expected: vec4(b.x, b.y, b.z, b.w) },
+ ],
+ };
+ break;
+ }
+ }
+
+ await run(
+ t,
+ builtin('select'),
+ [tests.dataType, tests.dataType, tests.boolType],
+ tests.dataType,
+ t.params,
+ tests.cases
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js
new file mode 100644
index 0000000000..ff83c910fd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sign.spec.js
@@ -0,0 +1,48 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'sign' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn sign(e: T ) -> T
+Returns the sign of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { signInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('sign', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', signInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('sign'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js
new file mode 100644
index 0000000000..e2b668f40a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sin.spec.js
@@ -0,0 +1,63 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'sin' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn sin(e: T ) -> T
+Returns the sine of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { sinInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('sin', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Well defined accuracy range
+ ...linearRange(-Math.PI, Math.PI, 1000),
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ sinInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(
+ `
+f32 tests
+
+TODO(#792): Decide what the ground-truth is for these tests. [1]
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('sin'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js
new file mode 100644
index 0000000000..5c492545a9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sinh.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'sinh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn sinh(e: T ) -> T
+Returns the hyperbolic sine of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { sinhInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('sinh', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'f32-only', sinhInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', sinhInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('sinh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js
new file mode 100644
index 0000000000..861282ff7b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/smoothstep.spec.js
@@ -0,0 +1,65 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'smoothstep' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn smoothstep(low: T , high: T , x: T ) -> T
+Returns the smooth Hermite interpolation between 0 and 1.
+Component-wise when T is a vector.
+For scalar T, the result is t * t * (3.0 - 2.0 * t), where t = clamp((x - low) / (high - low), 0.0, 1.0).
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { smoothStepInterval } from '../../../../../util/f32_interval.js';
+import { sparseF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateTernaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('smoothstep', {
+ f32_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'f32-only',
+ smoothStepInterval
+ );
+ },
+ f32_non_const: () => {
+ return generateTernaryToF32IntervalCases(
+ sparseF32Range(),
+ sparseF32Range(),
+ sparseF32Range(),
+ 'unfiltered',
+ smoothStepInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('smoothstep'), [TypeF32, TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js
new file mode 100644
index 0000000000..030fa7943c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/sqrt.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'sqrt' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn sqrt(e: T ) -> T
+Returns the square root of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { sqrtInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('sqrt', {
+ f32_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'f32-only', sqrtInterval);
+ },
+ f32_non_const: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', sqrtInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'f32_const' : 'f32_non_const');
+ await run(t, builtin('sqrt'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js
new file mode 100644
index 0000000000..01025d366c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/step.spec.js
@@ -0,0 +1,80 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'step' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn step(edge: T ,x: T ) -> T
+Returns 1.0 if edge ≤ x, and 0.0 otherwise. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { anyOf } from '../../../../../util/compare.js';
+import { f32, TypeF32 } from '../../../../../util/conversion.js';
+import { stepInterval, toF32Interval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, quantizeToF32 } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('step', {
+ f32: () => {
+ const zeroInterval = toF32Interval(0);
+ const oneInterval = toF32Interval(1);
+
+ // stepInterval's return value isn't always interpreted as an acceptance
+ // interval, so makeBinaryToF32IntervalCase cannot be used here.
+ // See the comment block on stepInterval for more details
+ const makeCase = (edge, x) => {
+ edge = quantizeToF32(edge);
+ x = quantizeToF32(x);
+ const expected = stepInterval(edge, x);
+
+ // [0, 0], [1, 1], or [-∞, +∞] cases
+ if (expected.isPoint() || !expected.isFinite()) {
+ return { input: [f32(edge), f32(x)], expected };
+ }
+
+ // [0, 1] case
+ return {
+ input: [f32(edge), f32(x)],
+ expected: anyOf(zeroInterval, oneInterval),
+ };
+ };
+
+ const range = fullF32Range();
+ const cases = [];
+ range.forEach(edge => {
+ range.forEach(x => {
+ cases.push(makeCase(edge, x));
+ });
+ });
+
+ return cases;
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('step'), [TypeF32, TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/storageBarrier.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/storageBarrier.spec.js
new file mode 100644
index 0000000000..ac7519ea92
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/storageBarrier.spec.js
@@ -0,0 +1,39 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+'storageBarrier' affects memory and atomic operations in the storage address space.
+
+All synchronization functions execute a control barrier with Acquire/Release memory ordering.
+That is, all synchronization functions, and affected memory and atomic operations are ordered
+in program order relative to the synchronization function. Additionally, the affected memory
+and atomic operations program-ordered before the synchronization function must be visible to
+all other threads in the workgroup before any affected memory or atomic operation program-ordered
+after the synchronization function is executed by a member of the workgroup. All synchronization
+functions use the Workgroup memory scope. All synchronization functions have a Workgroup
+execution scope.
+
+All synchronization functions must only be used in the compute shader stage.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions')
+ .desc(
+ `
+All synchronization functions must only be used in the compute shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['vertex', 'fragment', 'compute']))
+ .unimplemented();
+
+g.test('barrier')
+ .specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions')
+ .desc(
+ `
+fn storageBarrier()
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js
new file mode 100644
index 0000000000..8226ee6f37
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tan.spec.js
@@ -0,0 +1,57 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'tan' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn tan(e: T ) -> T
+Returns the tangent of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { tanInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range, linearRange } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('tan', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(
+ [
+ // Defined accuracy range
+ ...linearRange(-Math.PI, Math.PI, 100),
+ ...fullF32Range(),
+ ],
+
+ 'unfiltered',
+ tanInterval
+ );
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('tan'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js
new file mode 100644
index 0000000000..8720f27ac0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/tanh.spec.js
@@ -0,0 +1,48 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'tanh' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn tanh(e: T ) -> T
+Returns the hyperbolic tangent of e. Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { tanhInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('tanh', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', tanhInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('tanh'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js
new file mode 100644
index 0000000000..9a5ef4d829
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureDimension.spec.js
@@ -0,0 +1,161 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureDimension' builtin function
+
+The dimensions of the texture in texels.
+For textures based on cubes, the results are the dimensions of each face of the cube.
+Cube faces are square, so the x and y components of the result are equal.
+If level is outside the range [0, textureNumLevels(t)) then any valid value for the return type may be returned.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled')
+ .specURL('https://www.w3.org/TR/WGSL/#texturedimensions')
+ .desc(
+ `
+T: f32, i32, u32
+
+fn textureDimensions(t: texture_1d<T>) -> u32
+fn textureDimensions(t: texture_1d<T>, level: u32) -> u32
+fn textureDimensions(t: texture_2d<T>) -> vec2<u32>
+fn textureDimensions(t: texture_2d<T>, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_2d_array<T>) -> vec2<u32>
+fn textureDimensions(t: texture_2d_array<T>, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_3d<T>) -> vec3<u32>
+fn textureDimensions(t: texture_3d<T>, level: u32) -> vec3<u32>
+fn textureDimensions(t: texture_cube<T>) -> vec2<u32>
+fn textureDimensions(t: texture_cube<T>, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_cube_array<T>) -> vec2<u32>
+fn textureDimensions(t: texture_cube_array<T>, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_multisampled_2d<T>)-> vec2<u32>
+
+Parameters:
+ * t: the sampled texture
+ * level:
+ - The mip level, with level 0 containing a full size version of the texture.
+ - If omitted, the dimensions of level 0 are returned.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', [
+ 'texture_1d',
+ 'texture_2d',
+ 'texture_2d_array',
+ 'texture_3d',
+ 'texture_cube',
+ 'texture_cube_array',
+ 'texture_multisampled_2d',
+ ])
+ .beginSubcases()
+ .combine('sampled_type', ['f32-only', 'i32', 'u32'])
+ .combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1'])
+ )
+ .unimplemented();
+
+g.test('depth')
+ .specURL('https://www.w3.org/TR/WGSL/#texturedimensions')
+ .desc(
+ `
+fn textureDimensions(t: texture_depth_2d) -> vec2<u32>
+fn textureDimensions(t: texture_depth_2d, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_depth_2d_array) -> vec2<u32>
+fn textureDimensions(t: texture_depth_2d_array, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_depth_cube) -> vec2<u32>
+fn textureDimensions(t: texture_depth_cube, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_depth_cube_array) -> vec2<u32>
+fn textureDimensions(t: texture_depth_cube_array, level: u32) -> vec2<u32>
+fn textureDimensions(t: texture_depth_multisampled_2d)-> vec2<u32>
+
+Parameters:
+ * t: the depth or multisampled texture
+ * level:
+ - The mip level, with level 0 containing a full size version of the texture.
+ - If omitted, the dimensions of level 0 are returned.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', [
+ 'texture_depth_2d',
+ 'texture_depth_2d_array',
+ 'texture_depth_cube',
+ 'texture_depth_cube_array',
+ 'texture_depth_multisampled_2d',
+ ])
+ .beginSubcases()
+ .combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1'])
+ )
+ .unimplemented();
+
+g.test('storage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturedimensions')
+ .desc(
+ `
+F: rgba8unorm
+ rgba8snorm
+ rgba8uint
+ rgba8sint
+ rgba16uint
+ rgba16sint
+ rgba16float
+ r32uint
+ r32sint
+ r32float
+ rg32uint
+ rg32sint
+ rg32float
+ rgba32uint
+ rgba32sint
+ rgba32float
+A: read, write, read_write
+
+fn textureDimensions(t: texture_storage_1d<F,A>) -> u32
+fn textureDimensions(t: texture_storage_2d<F,A>) -> vec2<u32>
+fn textureDimensions(t: texture_storage_2d_array<F,A>) -> vec2<u32>
+fn textureDimensions(t: texture_storage_3d<F,A>) -> vec3<u32>
+
+Parameters:
+ * t: the storage texture
+`
+ )
+ .params(u =>
+ u
+ .combine('texel_format', [
+ 'rgba8unorm',
+ 'rgba8snorm',
+ 'rgba8uint',
+ 'rgba8sint',
+ 'rgba16uint',
+ 'rgba16sint',
+ 'rgba16float',
+ 'r32uint',
+ 'r32sint',
+ 'r32float',
+ 'rg32uint',
+ 'rg32sint',
+ 'rg32float',
+ 'rgba32uint',
+ 'rgba32sint',
+ 'rgba32float',
+ ])
+ .beginSubcases()
+ .combine('access_mode', ['read', 'write', 'read_write'])
+ )
+ .unimplemented();
+
+g.test('external')
+ .specURL('https://www.w3.org/TR/WGSL/#texturedimensions')
+ .desc(
+ `
+fn textureDimensions(t: texture_external) -> vec2<u32>
+
+Parameters:
+ * t: the external texture
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGather.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGather.spec.js
new file mode 100644
index 0000000000..1ecd1283d1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGather.spec.js
@@ -0,0 +1,275 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureGather' builtin function
+
+A texture gather operation reads from a 2D, 2D array, cube, or cube array texture, computing a four-component vector as follows:
+ * Find the four texels that would be used in a sampling operation with linear filtering, from mip level 0:
+ - Use the specified coordinate, array index (when present), and offset (when present).
+ - The texels are adjacent, forming a square, when considering their texture space coordinates (u,v).
+ - Selected texels at the texture edge, cube face edge, or cube corners are handled as in ordinary texture sampling.
+ * For each texel, read one channel and convert it into a scalar value.
+ - For non-depth textures, a zero-based component parameter specifies the channel to use.
+ * If the texture format supports the specified channel, i.e. has more than component channels:
+ - Yield scalar value v[component] when the texel value is v.
+ * Otherwise:
+ - Yield 0.0 when component is 1 or 2.
+ - Yield 1.0 when component is 3 (the alpha channel).
+ - For depth textures, yield the texel value. (Depth textures only have one channel.)
+ * Yield the four-component vector, arranging scalars produced by the previous step into components according to the relative coordinates of the texels, as follows:
+ - Result component Relative texel coordinate
+ x (umin,vmax)
+ y (umax,vmax)
+ z (umax,vmin)
+ w (umin,vmin)
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+T: i32, u32, f32
+
+fn textureGather(component: C, t: texture_2d<T>, s: sampler, coords: vec2<f32>) -> vec4<T>
+fn textureGather(component: C, t: texture_2d<T>, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<T>
+
+Parameters:
+ * component:
+ - The index of the channel to read from the selected texels.
+ - When provided, the component expression must a creation-time expression (e.g. 1).
+ - Its value must be at least 0 and at most 3. Values outside of this range will result in a shader-creation error.
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('T', ['f32-only', 'i32', 'u32'])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+T: i32, u32, f32
+
+fn textureGather(component: C, t: texture_cube<T>, s: sampler, coords: vec3<f32>) -> vec4<T>
+
+Parameters:
+ * component:
+ - The index of the channel to read from the selected texels.
+ - When provided, the component expression must a creation-time expression (e.g. 1).
+ - Its value must be at least 0 and at most 3. Values outside of this range will result in a shader-creation error.
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('T', ['f32-only', 'i32', 'u32'])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ )
+ .unimplemented();
+
+g.test('sampled_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+T: i32, u32, f32
+
+fn textureGather(component: C, t: texture_2d_array<T>, s: sampler, coords: vec2<f32>, array_index: C) -> vec4<T>
+fn textureGather(component: C, t: texture_2d_array<T>, s: sampler, coords: vec2<f32>, array_index: C, offset: vec2<i32>) -> vec4<T>
+
+Parameters:
+ * component:
+ - The index of the channel to read from the selected texels.
+ - When provided, the component expression must a creation-time expression (e.g. 1).
+ - Its value must be at least 0 and at most 3. Values outside of this range will result in a shader-creation error.
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('T', ['f32-only', 'i32', 'u32'])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'offset',
+ generateOffsets(2)
+ )
+ )
+ .unimplemented();
+
+g.test('sampled_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+T: i32, u32, f32
+
+fn textureGather(component: C, t: texture_cube_array<T>, s: sampler, coords: vec3<f32>, array_index: C) -> vec4<T>
+
+Parameters:
+ * component:
+ - The index of the channel to read from the selected texels.
+ - When provided, the component expression must a creation-time expression (e.g. 1).
+ - Its value must be at least 0 and at most 3. Values outside of this range will result in a shader-creation error.
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index
+`
+ )
+ .paramsSubcasesOnly(
+ u =>
+ u
+ .combine('T', ['f32-only', 'i32', 'u32'])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */
+ )
+ .unimplemented();
+
+g.test('depth_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+fn textureGather(t: texture_depth_2d, s: sampler, coords: vec2<f32>) -> vec4<f32>
+fn textureGather(t: texture_depth_2d, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('depth_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+fn textureGather(t: texture_depth_cube, s: sampler, coords: vec3<f32>) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ )
+ .unimplemented();
+
+g.test('depth_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+
+fn textureGather(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C) -> vec4<f32>
+fn textureGather(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'offset',
+ generateOffsets(2)
+ )
+ )
+ .unimplemented();
+
+g.test('depth_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegather')
+ .desc(
+ `
+C: i32, u32
+
+fn textureGather(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: C) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index
+`
+ )
+ .paramsSubcasesOnly(
+ u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.js
new file mode 100644
index 0000000000..ddb24c472e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.js
@@ -0,0 +1,135 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureGatherCompare' builtin function
+
+A texture gather compare operation performs a depth comparison on four texels in a depth texture and collects the results into a single vector, as follows:
+ * Find the four texels that would be used in a depth sampling operation with linear filtering, from mip level 0:
+ - Use the specified coordinate, array index (when present), and offset (when present).
+ - The texels are adjacent, forming a square, when considering their texture space coordinates (u,v).
+ - Selected texels at the texture edge, cube face edge, or cube corners are handled as in ordinary texture sampling.
+ * For each texel, perform a comparison against the depth reference value, yielding a 0.0 or 1.0 value, as controlled by the comparison sampler parameters.
+ * Yield the four-component vector where the components are the comparison results with the texels with relative texel coordinates as follows:
+
+ Result component Relative texel coordinate
+ x (umin,vmax)
+ y (umax,vmax)
+ z (umax,vmin)
+ w (umin,vmin)
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegathercompare')
+ .desc(
+ `
+C: i32, u32
+
+fn textureGatherCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32) -> vec4<f32>
+fn textureGatherCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler_comparison
+ * coords: The texture coordinates
+ * array_index: The 0-based array index.
+ * depth_ref: The reference value to compare the sampled depth value against
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegathercompare')
+ .desc(
+ `
+C: i32, u32
+
+fn textureGatherCompare(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: C, depth_ref: f32) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler_comparison
+ * coords: The texture coordinates
+ * array_index: The 0-based array index.
+ * depth_ref: The reference value to compare the sampled depth value against
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ )
+ .unimplemented();
+
+g.test('sampled_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegathercompare')
+ .desc(
+ `
+fn textureGatherCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> vec4<f32>
+fn textureGatherCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler_comparison
+ * coords: The texture coordinates
+ * depth_ref: The reference value to compare the sampled depth value against
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturegathercompare')
+ .desc(
+ `
+fn textureGatherCompare(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> vec4<f32>
+
+Parameters:
+ * t: The depth texture to read from
+ * s: The sampler_comparison
+ * coords: The texture coordinates
+ * depth_ref: The reference value to compare the sampled depth value against
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureLoad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureLoad.spec.js
new file mode 100644
index 0000000000..c11d20554b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureLoad.spec.js
@@ -0,0 +1,183 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureLoad' builtin function
+
+Reads a single texel from a texture without sampling or filtering.
+
+Returns the unfiltered texel data.
+
+An out of bounds access occurs if:
+ * any element of coords is outside the range [0, textureDimensions(t, level)) for the corresponding element, or
+ * array_index is outside the range [0, textureNumLayers(t)), or
+ * level is outside the range [0, textureNumLevels(t))
+
+If an out of bounds access occurs, the built-in function returns one of:
+ * The data for some texel within bounds of the texture
+ * A vector (0,0,0,0) or (0,0,0,1) of the appropriate type for non-depth textures
+ * 0.0 for depth textures
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled_1d')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_1d<T>, coords: C, level: C) -> vec4<T>
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * level: The mip level, with level 0 containing a full size version of the texture
+`
+ )
+ .params(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(1))
+ .combine('level', [-1, 0, `numlevels-1`, `numlevels`])
+ )
+ .unimplemented();
+
+g.test('sampled_2d')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_2d<T>, coords: vec2<C>, level: C) -> vec4<T>
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * level: The mip level, with level 0 containing a full size version of the texture
+`
+ )
+ .params(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('level', [-1, 0, `numlevels-1`, `numlevels`])
+ )
+ .unimplemented();
+
+g.test('sampled_3d')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_3d<T>, coords: vec3<C>, level: C) -> vec4<T>
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * level: The mip level, with level 0 containing a full size version of the texture
+`
+ )
+ .params(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('level', [-1, 0, `numlevels-1`, `numlevels`])
+ )
+ .unimplemented();
+
+g.test('multisampled')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_multisampled_2d<T>, coords: vec2<C>, sample_index: C)-> vec4<T>
+fn textureLoad(t: texture_depth_multisampled_2d, coords: vec2<C>, sample_index: C)-> f32
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * sample_index: The 0-based sample index of the multisampled texture
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_multisampled_2d', 'texture_depth_multisampled_2d'])
+ .beginSubcases()
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('sample_index', [-1, 0, `sampleCount-1`, `sampleCount`])
+ )
+ .unimplemented();
+
+g.test('depth')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_depth_2d, coords: vec2<C>, level: C) -> f32
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * level: The mip level, with level 0 containing a full size version of the texture
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('level', [-1, 0, `numlevels-1`, `numlevels`])
+ )
+ .unimplemented();
+
+g.test('external')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_external, coords: vec2<C>) -> vec4<f32>
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u.combine('C', ['i32', 'u32']).combine('coords', generateCoordBoundaries(2))
+ )
+ .unimplemented();
+
+g.test('arrayed')
+ .specURL('https://www.w3.org/TR/WGSL/#textureload')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureLoad(t: texture_2d_array<T>, coords: vec2<C>, array_index: C, level: C) -> vec4<T>
+fn textureLoad(t: texture_depth_2d_array, coords: vec2<C>, array_index: C, level: C) -> f32
+
+Parameters:
+ * t: The sampled texture to read from
+ * coords: The 0-based texel coordinate
+ * array_index: The 0-based texture array index
+ * level: The mip level, with level 0 containing a full size version of the texture
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_2d_array', 'texture_depth_2d_array'])
+ .beginSubcases()
+ .combine('C', ['i32', 'u32'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('array_index', [-1, 0, `numlayers-1`, `numlayers`])
+ .combine('level', [-1, 0, `numlevels-1`, `numlevels`])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLayers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLayers.spec.js
new file mode 100644
index 0000000000..5b0372289d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLayers.spec.js
@@ -0,0 +1,99 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureNumLayers' builtin function
+
+Returns the number of layers (elements) of an array texture.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumlayers')
+ .desc(
+ `
+T, a sampled type.
+
+fn textureNumLayers(t: texture_2d_array<T>) -> u32
+fn textureNumLayers(t: texture_cube_array<T>) -> u32
+
+Parameters
+ * t The sampled array texture.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_2d_array', 'texture_cube_array'])
+ .beginSubcases()
+ .combine('sampled_type', ['f32-only', 'i32', 'u32'])
+ )
+ .unimplemented();
+
+g.test('arrayed')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumlayers')
+ .desc(
+ `
+fn textureNumLayers(t: texture_depth_2d_array) -> u32
+fn textureNumLayers(t: texture_depth_cube_array) -> u32
+
+Parameters
+ * t The depth array texture.
+`
+ )
+ .params(u => u.combine('texture_type', ['texture_depth_2d_array', 'texture_depth_cube_array']))
+ .unimplemented();
+
+g.test('storage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumlayers')
+ .desc(
+ `
+F: rgba8unorm
+ rgba8snorm
+ rgba8uint
+ rgba8sint
+ rgba16uint
+ rgba16sint
+ rgba16float
+ r32uint
+ r32sint
+ r32float
+ rg32uint
+ rg32sint
+ rg32float
+ rgba32uint
+ rgba32sint
+ rgba32float
+A: read, write, read_write
+
+fn textureNumLayers(t: texture_storage_2d_array<F,A>) -> u32
+
+Parameters
+ * t The sampled storage array texture.
+`
+ )
+ .params(u =>
+ u
+ .beginSubcases()
+ .combine('texel_format', [
+ 'rgba8unorm',
+ 'rgba8snorm',
+ 'rgba8uint',
+ 'rgba8sint',
+ 'rgba16uint',
+ 'rgba16sint',
+ 'rgba16float',
+ 'r32uint',
+ 'r32sint',
+ 'r32float',
+ 'rg32uint',
+ 'rg32sint',
+ 'rg32float',
+ 'rgba32uint',
+ 'rgba32sint',
+ 'rgba32float',
+ ])
+ .combine('access_mode', ['read', 'write', 'read_write'])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLevels.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLevels.spec.js
new file mode 100644
index 0000000000..ae59dd99bb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumLevels.spec.js
@@ -0,0 +1,66 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureNumLevels' builtin function
+
+Returns the number of mip levels of a texture.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumlevels')
+ .desc(
+ `
+T, a sampled type.
+
+fn textureNumLevels(t: texture_1d<T>) -> u32
+fn textureNumLevels(t: texture_2d<T>) -> u32
+fn textureNumLevels(t: texture_2d_array<T>) -> u32
+fn textureNumLevels(t: texture_3d<T>) -> u32
+fn textureNumLevels(t: texture_cube<T>) -> u32
+fn textureNumLevels(t: texture_cube_array<T>) -> u32
+
+Parameters
+ * t The sampled array texture.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', [
+ 'texture_1d',
+ 'texture_2d',
+ 'texture_2d_array',
+ 'texture_3d',
+ 'texture_cube',
+ 'texture_cube_array`',
+ ])
+ .beginSubcases()
+ .combine('sampled_type', ['f32-only', 'i32', 'u32'])
+ )
+ .unimplemented();
+
+g.test('depth')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumlevels')
+ .desc(
+ `
+fn textureNumLevels(t: texture_depth_2d) -> u32
+fn textureNumLevels(t: texture_depth_2d_array) -> u32
+fn textureNumLevels(t: texture_depth_cube) -> u32
+fn textureNumLevels(t: texture_depth_cube_array) -> u32
+
+Parameters
+ * t The depth array texture.
+`
+ )
+ .params(u =>
+ u.combine('texture_type', [
+ 'texture_depth_2d',
+ 'texture_depth_2d_array',
+ 'texture_depth_cube',
+ 'texture_depth_cube_array',
+ ])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumSamples.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumSamples.spec.js
new file mode 100644
index 0000000000..620d1a7e9d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureNumSamples.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureNumSamples' builtin function
+
+Returns the number samples per texel in a multisampled texture.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumsamples')
+ .desc(
+ `
+T, a sampled type.
+
+fn textureNumSamples(t: texture_multisampled_2d<T>) -> u32
+
+Parameters
+ * t The multisampled texture.
+`
+ )
+ .params(u => u.beginSubcases().combine('sampled_type', ['f32-only', 'i32', 'u32']))
+ .unimplemented();
+
+g.test('depth')
+ .specURL('https://www.w3.org/TR/WGSL/#texturenumsamples')
+ .desc(
+ `
+fn textureNumSamples(t: texture_depth_multisampled_2d) -> u32
+
+Parameters
+ * t The multisampled texture.
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js
new file mode 100644
index 0000000000..6d39c22531
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSample.spec.js
@@ -0,0 +1,278 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Samples a texture.
+
+Must only be used in a fragment shader stage.
+Must only be invoked in uniform control flow.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+Tests that 'textureSample' can only be called in 'fragment' shaders.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('control_flow')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+Tests that 'textureSample' can only be called in uniform control flow.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('sampled_1d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+fn textureSample(t: texture_1d<f32>, s: sampler, coords: f32) -> vec4<f32>
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(1))
+ )
+ .unimplemented();
+
+g.test('sampled_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+fn textureSample(t: texture_2d<f32>, s: sampler, coords: vec2<f32>) -> vec4<f32>
+fn textureSample(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+fn textureSample(t: texture_3d<f32>, s: sampler, coords: vec3<f32>) -> vec4<f32>
+fn textureSample(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, offset: vec3<i32>) -> vec4<f32>
+fn textureSample(t: texture_cube<f32>, s: sampler, coords: vec3<f32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_3d', 'texture_cube'])
+ .beginSubcases()
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('offset', generateOffsets(3))
+ )
+ .unimplemented();
+
+g.test('depth_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+fn textureSample(t: texture_depth_2d, s: sampler, coords: vec2<f32>) -> f32
+fn textureSample(t: texture_depth_2d, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSample(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C) -> vec4<f32>
+fn textureSample(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'offset',
+ generateOffsets(2)
+ )
+ )
+ .unimplemented();
+
+g.test('sampled_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSample(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: C) -> vec4<f32>
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+`
+ )
+ .paramsSubcasesOnly(
+ u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */
+ )
+ .unimplemented();
+
+g.test('depth_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+fn textureSample(t: texture_depth_cube, s: sampler, coords: vec3<f32>) -> f32
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ )
+ .unimplemented();
+
+g.test('depth_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSample(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C) -> f32
+fn textureSample(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'offset',
+ generateOffsets(2)
+ )
+ )
+ .unimplemented();
+
+g.test('depth_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesample')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSample(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: C) -> f32
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+`
+ )
+ .paramsSubcasesOnly(
+ u =>
+ u
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js
new file mode 100644
index 0000000000..f74b3a0ba0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleBias.spec.js
@@ -0,0 +1,176 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'textureSampleBias' builtin function
+
+Samples a texture with a bias to the mip level.
+Must only be used in a fragment shader stage.
+Must only be invoked in uniform control flow.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+Tests that 'textureSampleBias' can only be called in 'fragment' shaders.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('control_flow')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+Tests that 'textureSampleBias' can only be called in uniform control flow.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('sampled_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+fn textureSampleBias(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32>
+fn textureSampleBias(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, bias: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * bias: The bias to apply to the mip level before sampling. bias must be between -16.0 and 15.99.
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('bias', [-16.1, -16, 0, 1, 15.99, 16])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+fn textureSampleBias(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
+fn textureSampleBias(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, bias: f32, offset: vec3<i32>) -> vec4<f32>
+fn textureSampleBias(t: texture_cube<f32>, s: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32>
+
+Parameters:
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * bias: The bias to apply to the mip level before sampling. bias must be between -16.0 and 15.99.
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_3d', 'texture_cube'])
+ .beginSubcases()
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('bias', [-16.1, -16, 0, 1, 15.99, 16])
+ .combine('offset', generateOffsets(3))
+ )
+ .unimplemented();
+
+g.test('arrayed_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+C: i32, u32
+
+fn textureSampleBias(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, bias: f32) -> vec4<f32>
+fn textureSampleBias(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, bias: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index to sample.
+ * bias: The bias to apply to the mip level before sampling. bias must be between -16.0 and 15.99.
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('bias', [
+ -16.1,
+ -16,
+ 0,
+ 1,
+ 15.99,
+ 16,
+ ])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('arrayed_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplebias')
+ .desc(
+ `
+C: i32, u32
+
+fn textureSampleBias(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: C, bias: f32) -> vec4<f32>
+
+Parameters:
+ * t: The sampled texture to read from
+ * s: The sampler type
+ * coords: The texture coordinates
+ * array_index: The 0-based texture array index to sample.
+ * bias: The bias to apply to the mip level before sampling. bias must be between -16.0 and 15.99.
+ * offset:
+ - The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ This offset is applied before applying any texture wrapping modes.
+ - The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ - Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('bias', [
+ -16.1,
+ -16,
+ 0,
+ 1,
+ 15.99,
+ 16,
+ ])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js
new file mode 100644
index 0000000000..c0a4c2b68a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompare.spec.js
@@ -0,0 +1,150 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Samples a depth texture and compares the sampled depth values against a reference value.
+
+Must only be used in a fragment shader stage.
+Must only be invoked in uniform control flow.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+Tests that 'textureSampleCompare' can only be called in 'fragment' shaders.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('control_flow')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+Tests that 'textureSampleCompare' can only be called in uniform control flow.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+fn textureSampleCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32
+fn textureSampleCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * depth_ref The reference value to compare the sampled depth value against.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+fn textureSampleCompare(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * depth_ref The reference value to compare the sampled depth value against.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ )
+ .unimplemented();
+
+g.test('arrayed_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32) -> f32
+fn textureSampleCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * array_index: The 0-based texture array index to sample.
+ * depth_ref The reference value to compare the sampled depth value against.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'depth_ref',
+ [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */]
+ )
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('arrayed_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecompare')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleCompare(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: C, depth_ref: f32) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * array_index: The 0-based texture array index to sample.
+ * depth_ref The reference value to compare the sampled depth value against.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'depth_ref',
+ [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */]
+ )
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompareLevel.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompareLevel.spec.js
new file mode 100644
index 0000000000..24e7453b6d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleCompareLevel.spec.js
@@ -0,0 +1,154 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Samples a depth texture and compares the sampled depth values against a reference value.
+
+The textureSampleCompareLevel function is the same as textureSampleCompare, except that:
+
+ * textureSampleCompareLevel always samples texels from mip level 0.
+ * The function does not compute derivatives.
+ * There is no requirement for textureSampleCompareLevel to be invoked in uniform control flow.
+ * textureSampleCompareLevel may be invoked in any shader stage.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+Tests that 'textureSampleCompareLevel' maybe called in any shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('control_flow')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+Tests that 'textureSampleCompareLevel' maybe called in non-uniform control flow.
+`
+ )
+ .params(u => u.combine('stage', ['fragment', 'vertex', 'compute']))
+ .unimplemented();
+
+g.test('2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+fn textureSampleCompareLevel(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32
+fn textureSampleCompareLevel(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * depth_ref The reference value to compare the sampled depth value against.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+fn textureSampleCompareLevel(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * depth_ref The reference value to compare the sampled depth value against.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('depth_ref', [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */])
+ )
+ .unimplemented();
+
+g.test('arrayed_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleCompareLevel(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32) -> f32
+fn textureSampleCompareLevel(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: C, depth_ref: f32, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * array_index: The 0-based texture array index to sample.
+ * depth_ref The reference value to compare the sampled depth value against.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'depth_ref',
+ [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */]
+ )
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('arrayed_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplecomparelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleCompareLevel(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: C, depth_ref: f32) -> f32
+
+Parameters:
+ * t The depth texture to sample.
+ * s The sampler_comparision type.
+ * coords The texture coordinates used for sampling.
+ * array_index: The 0-based texture array index to sample.
+ * depth_ref The reference value to compare the sampled depth value against.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'depth_ref',
+ [-1 /* smaller ref */, 0 /* equal ref */, 1 /* larger ref */]
+ )
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleGrad.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleGrad.spec.js
new file mode 100644
index 0000000000..bb77a66a27
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleGrad.spec.js
@@ -0,0 +1,139 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Samples a texture using explicit gradients.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplegrad')
+ .desc(
+ `
+fn textureSampleGrad(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32>
+fn textureSampleGrad(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled texture.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * ddx The x direction derivative vector used to compute the sampling locations
+ * ddy The y direction derivative vector used to compute the sampling locations
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ )
+ .unimplemented();
+
+g.test('sampled_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplegrad')
+ .desc(
+ `
+fn textureSampleGrad(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32>
+fn textureSampleGrad(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>, offset: vec3<i32>) -> vec4<f32>
+fn textureSampleGrad(t: texture_cube<f32>, s: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled texture.
+ * s The sampler type.
+ * ddx The x direction derivative vector used to compute the sampling locations
+ * ddy The y direction derivative vector used to compute the sampling locations
+ * coords The texture coordinates used for sampling.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('offset', generateOffsets(3))
+ )
+ .unimplemented();
+
+g.test('sampled_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplegrad')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleGrad(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32>
+fn textureSampleGrad(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled texture.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * ddx The x direction derivative vector used to compute the sampling locations
+ * ddy The y direction derivative vector used to compute the sampling locations
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine(
+ 'offset',
+ generateOffsets(2)
+ )
+ )
+ .unimplemented();
+
+g.test('sampled_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplegrad')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleGrad(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: C, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled texture.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * ddx The x direction derivative vector used to compute the sampling locations
+ * ddy The y direction derivative vector used to compute the sampling locations
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleLevel.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleLevel.spec.js
new file mode 100644
index 0000000000..5d3b8ca78c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureSampleLevel.spec.js
@@ -0,0 +1,295 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Samples a texture.
+
+Must only be used in a fragment shader stage.
+Must only be invoked in uniform control flow.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+import { generateCoordBoundaries, generateOffsets } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('sampled_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+fn textureSampleLevel(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, level: f32) -> vec4<f32>
+fn textureSampleLevel(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, level: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ .combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1'])
+ )
+ .unimplemented();
+
+g.test('sampled_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleLevel(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, level: f32) -> vec4<f32>
+fn textureSampleLevel(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: C, level: f32, offset: vec2<i32>) -> vec4<f32>
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('level', [
+ undefined,
+ 0,
+ 1,
+ 'textureNumLevels',
+ 'textureNumLevels+1',
+ ])
+ )
+ .unimplemented();
+
+g.test('sampled_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+fn textureSampleLevel(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, level: f32) -> vec4<f32>
+fn textureSampleLevel(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, level: f32, offset: vec3<i32>) -> vec4<f32>
+fn textureSampleLevel(t: texture_cube<f32>, s: sampler, coords: vec3<f32>, level: f32) -> vec4<f32>
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_3d', 'texture_cube'])
+ .beginSubcases()
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('offset', generateOffsets(3))
+ .combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1'])
+ )
+ .unimplemented();
+
+g.test('sampled_array_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleLevel(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: C, level: f32) -> vec4<f32>
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * array_index The 0-based texture array index to sample.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('offset', generateOffsets(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('level', [
+ undefined,
+ 0,
+ 1,
+ 'textureNumLevels',
+ 'textureNumLevels+1',
+ ])
+ )
+ .unimplemented();
+
+g.test('depth_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleLevel(t: texture_depth_2d, s: sampler, coords: vec2<f32>, level: C) -> f32
+fn textureSampleLevel(t: texture_depth_2d, s: sampler, coords: vec2<f32>, level: C, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ .combine('level', [undefined, 0, 1, 'textureNumLevels', 'textureNumLevels+1'])
+ )
+ .unimplemented();
+
+g.test('depth_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleLevel(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C, level: C) -> f32
+fn textureSampleLevel(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: C, level: C, offset: vec2<i32>) -> f32
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * array_index The 0-based texture array index to sample.
+ * coords The texture coordinates used for sampling.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .paramsSubcasesOnly(u =>
+ u
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('offset', generateOffsets(2))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('level', [
+ undefined,
+ 0,
+ 1,
+ 'textureNumLevels',
+ 'textureNumLevels+1',
+ ])
+ )
+ .unimplemented();
+
+g.test('depth_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturesamplelevel')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureSampleLevel(t: texture_depth_cube, s: sampler, coords: vec3<f32>, level: C) -> f32
+fn textureSampleLevel(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: C, level: C) -> f32
+
+Parameters:
+ * t The sampled or depth texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * level
+ * The mip level, with level 0 containing a full size version of the texture.
+ * For the functions where level is a f32, fractional values may interpolate between
+ two levels if the format is filterable according to the Texture Format Capabilities.
+ * When not specified, mip level 0 is sampled.
+ * offset
+ * The optional texel offset applied to the unnormalized texture coordinate before sampling the texture.
+ * This offset is applied before applying any texture wrapping modes.
+ * The offset expression must be a creation-time expression (e.g. vec2<i32>(1, 2)).
+ * Each offset component must be at least -8 and at most 7.
+ Values outside of this range will result in a shader-creation error.
+`
+ )
+ .params(u =>
+ u
+ .combine('texture_type', ['texture_depth_cube', 'texture_depth_cube_array'])
+ .beginSubcases()
+ .combine('S', ['clamp-to-edge', 'repeat', 'mirror-repeat'])
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ .combine('coords', generateCoordBoundaries(3))
+ /* array_index not param'd as out-of-bounds is implementation specific */ .combine('level', [
+ undefined,
+ 0,
+ 1,
+ 'textureNumLevels',
+ 'textureNumLevels+1',
+ ])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureStore.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureStore.spec.js
new file mode 100644
index 0000000000..cd555f429b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/textureStore.spec.js
@@ -0,0 +1,123 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Writes a single texel to a texture.
+
+The channel format T depends on the storage texel format F.
+See the texel format table for the mapping of texel format to channel format.
+
+Note: An out-of-bounds access occurs if:
+ * any element of coords is outside the range [0, textureDimensions(t)) for the corresponding element, or
+ * array_index is outside the range of [0, textureNumLayers(t))
+
+If an out-of-bounds access occurs, the built-in function may do any of the following:
+ * not be executed
+ * store value to some in bounds texel
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TexelFormats } from '../../../../types.js';
+
+import { generateCoordBoundaries } from './utils.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('store_1d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturestore')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureStore(t: texture_storage_1d<F,write>, coords: C, value: vec4<T>)
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * value The new texel value
+`
+ )
+ .params(u =>
+ u
+ .combineWithParams(TexelFormats)
+ .beginSubcases()
+ .combine('coords', generateCoordBoundaries(1))
+ .combine('C', ['i32', 'u32'])
+ )
+ .unimplemented();
+
+g.test('store_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturestore')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureStore(t: texture_storage_2d<F,write>, coords: vec2<C>, value: vec4<T>)
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * value The new texel value
+`
+ )
+ .params(u =>
+ u
+ .combineWithParams(TexelFormats)
+ .beginSubcases()
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('C', ['i32', 'u32'])
+ )
+ .unimplemented();
+
+g.test('store_array_2d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturestore')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureStore(t: texture_storage_2d_array<F,write>, coords: vec2<C>, array_index: C, value: vec4<T>)
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * array_index The 0-based texture array index
+ * coords The texture coordinates used for sampling.
+ * value The new texel value
+`
+ )
+ .params(
+ u =>
+ u
+ .combineWithParams(TexelFormats)
+ .beginSubcases()
+ .combine('coords', generateCoordBoundaries(2))
+ .combine('C', ['i32', 'u32'])
+ .combine('C_value', [-1, 0, 1, 2, 3, 4])
+ /* array_index not param'd as out-of-bounds is implementation specific */
+ )
+ .unimplemented();
+
+g.test('store_3d_coords')
+ .specURL('https://www.w3.org/TR/WGSL/#texturestore')
+ .desc(
+ `
+C is i32 or u32
+
+fn textureStore(t: texture_storage_3d<F,write>, coords: vec3<C>, value: vec4<T>)
+
+Parameters:
+ * t The sampled, depth, or external texture to sample.
+ * s The sampler type.
+ * coords The texture coordinates used for sampling.
+ * value The new texel value
+`
+ )
+ .params(u =>
+ u
+ .combineWithParams(TexelFormats)
+ .beginSubcases()
+ .combine('coords', generateCoordBoundaries(3))
+ .combine('C', ['i32', 'u32'])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js
new file mode 100644
index 0000000000..cc0353c2c1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/transpose.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'transpose' builtin function
+
+T is AbstractFloat, f32, or f16
+@const transpose(e: matRxC<T> ) -> matCxR<T>
+Returns the transpose of e.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { allInputSources } from '../../expression.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u =>
+ u.combine('inputSource', allInputSources).combine('rows', [2, 3, 4]).combine('cols', [2, 3, 4])
+ )
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u =>
+ u.combine('inputSource', allInputSources).combine('rows', [2, 3, 4]).combine('cols', [2, 3, 4])
+ )
+ .unimplemented();
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u =>
+ u.combine('inputSource', allInputSources).combine('rows', [2, 3, 4]).combine('cols', [2, 3, 4])
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js
new file mode 100644
index 0000000000..47460fb5c4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/trunc.spec.js
@@ -0,0 +1,49 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution tests for the 'trunc' builtin function
+
+S is AbstractFloat, f32, f16
+T is S or vecN<S>
+@const fn trunc(e: T ) -> T
+Returns the nearest whole number whose absolute value is less than or equal to e.
+Component-wise when T is a vector.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32 } from '../../../../../util/conversion.js';
+import { truncInterval } from '../../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('trunc', {
+ f32: () => {
+ return generateUnaryToF32IntervalCases(fullF32Range(), 'unfiltered', truncInterval);
+ },
+});
+
+g.test('abstract_float')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`abstract float tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
+
+g.test('f32')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f32 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('f32');
+ await run(t, builtin('trunc'), [TypeF32], TypeF32, t.params, cases);
+ });
+
+g.test('f16')
+ .specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
+ .desc(`f16 tests`)
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js
new file mode 100644
index 0000000000..f1c5335c9f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16float.spec.js
@@ -0,0 +1,41 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Decomposes a 32-bit value into two 16-bit chunks, and reinterpets each chunk as
+a floating point value.
+Component i of the result is the f32 representation of v, where v is the
+interpretation of bits 16×i through 16×i+15 of e as an IEEE-754 binary16 value.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js';
+import { unpack2x16floatInterval } from '../../../../../util/f32_interval.js';
+import { fullU32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateU32ToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unpack2x16float', {
+ u32_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'f32-only', unpack2x16floatInterval);
+ },
+ u32_non_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'unfiltered', unpack2x16floatInterval);
+ },
+});
+
+g.test('unpack')
+ .specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions')
+ .desc(
+ `
+@const fn unpack2x16float(e: u32) -> vec2<f32>
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const');
+ await run(t, builtin('unpack2x16float'), [TypeU32], TypeVec(2, TypeF32), t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js
new file mode 100644
index 0000000000..f7288602bb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16snorm.spec.js
@@ -0,0 +1,41 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Decomposes a 32-bit value into two 16-bit chunks, then reinterprets each chunk
+as a signed normalized floating point value.
+Component i of the result is max(v ÷ 32767, -1), where v is the interpretation
+of bits 16×i through 16×i+15 of e as a twos-complement signed integer.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js';
+import { unpack2x16snormInterval } from '../../../../../util/f32_interval.js';
+import { fullU32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateU32ToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unpack2x16snorm', {
+ u32_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'f32-only', unpack2x16snormInterval);
+ },
+ u32_non_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'unfiltered', unpack2x16snormInterval);
+ },
+});
+
+g.test('unpack')
+ .specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions')
+ .desc(
+ `
+@const fn unpack2x16snorm(e: u32) -> vec2<f32>
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const');
+ await run(t, builtin('unpack2x16snorm'), [TypeU32], TypeVec(2, TypeF32), t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js
new file mode 100644
index 0000000000..33deeadc67
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack2x16unorm.spec.js
@@ -0,0 +1,41 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Decomposes a 32-bit value into two 16-bit chunks, then reinterprets each chunk
+as an unsigned normalized floating point value.
+Component i of the result is v ÷ 65535, where v is the interpretation of bits
+16×i through 16×i+15 of e as an unsigned integer.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js';
+import { unpack2x16unormInterval } from '../../../../../util/f32_interval.js';
+import { fullU32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateU32ToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unpack2x16unorm', {
+ u32_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'f32-only', unpack2x16unormInterval);
+ },
+ u32_non_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'unfiltered', unpack2x16unormInterval);
+ },
+});
+
+g.test('unpack')
+ .specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions')
+ .desc(
+ `
+@const fn unpack2x16unorm(e: u32) -> vec2<f32>
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const');
+ await run(t, builtin('unpack2x16unorm'), [TypeU32], TypeVec(2, TypeF32), t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js
new file mode 100644
index 0000000000..35d372c521
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.js
@@ -0,0 +1,41 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Decomposes a 32-bit value into four 8-bit chunks, then reinterprets each chunk
+as a signed normalized floating point value.
+Component i of the result is max(v ÷ 127, -1), where v is the interpretation of
+bits 8×i through 8×i+7 of e as a twos-complement signed integer.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js';
+import { unpack4x8snormInterval } from '../../../../../util/f32_interval.js';
+import { fullU32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateU32ToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unpack4x8snorm', {
+ u32_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'f32-only', unpack4x8snormInterval);
+ },
+ u32_non_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'unfiltered', unpack4x8snormInterval);
+ },
+});
+
+g.test('unpack')
+ .specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions')
+ .desc(
+ `
+@const fn unpack4x8snorm(e: u32) -> vec4<f32>
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const');
+ await run(t, builtin('unpack4x8snorm'), [TypeU32], TypeVec(4, TypeF32), t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js
new file mode 100644
index 0000000000..6b4f944f6f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.js
@@ -0,0 +1,41 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Decomposes a 32-bit value into four 8-bit chunks, then reinterprets each chunk
+as an unsigned normalized floating point value.
+Component i of the result is v ÷ 255, where v is the interpretation of bits 8×i
+through 8×i+7 of e as an unsigned integer.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+import { TypeF32, TypeU32, TypeVec } from '../../../../../util/conversion.js';
+import { unpack4x8unormInterval } from '../../../../../util/f32_interval.js';
+import { fullU32Range } from '../../../../../util/math.js';
+import { makeCaseCache } from '../../case_cache.js';
+import { allInputSources, generateU32ToVectorCases, run } from '../../expression.js';
+
+import { builtin } from './builtin.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unpack4x8unorm', {
+ u32_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'f32-only', unpack4x8unormInterval);
+ },
+ u32_non_const: () => {
+ return generateU32ToVectorCases(fullU32Range(), 'unfiltered', unpack4x8unormInterval);
+ },
+});
+
+g.test('unpack')
+ .specURL('https://www.w3.org/TR/WGSL/#unpack-builtin-functions')
+ .desc(
+ `
+@const fn unpack4x8unorm(e: u32) -> vec4<f32>
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources))
+ .fn(async t => {
+ const cases = await d.get(t.params.inputSource === 'const' ? 'u32_const' : 'u32_non_const');
+ await run(t, builtin('unpack4x8unorm'), [TypeU32], TypeVec(4, TypeF32), t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/utils.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/utils.js
new file mode 100644
index 0000000000..cdc7d1a985
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/utils.js
@@ -0,0 +1,46 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * Generates the boundary entries for the given number of dimensions
+ *
+ * @param numDimensions: The number of dimensions to generate for
+ * @returns an array of generated coord boundaries
+ */ export function generateCoordBoundaries(numDimensions) {
+ const ret = ['in-bounds'];
+
+ if (numDimensions < 1 || numDimensions > 3) {
+ throw new Error(`invalid numDimensions: ${numDimensions}`);
+ }
+
+ const name = 'xyz';
+ for (let i = 0; i < numDimensions; ++i) {
+ for (const j of ['min', 'max']) {
+ for (const k of ['wrap', 'boundary']) {
+ ret.push(`${name[i]}-${j}-${k}`);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Generates a set of offset values to attempt in the range [-9, 8].
+ *
+ * @param numDimensions: The number of dimensions to generate for
+ * @return an array of generated offset values
+ */
+export function generateOffsets(numDimensions) {
+ if (numDimensions < 2 || numDimensions > 3) {
+ throw new Error(`generateOffsets: invalid numDimensions: ${numDimensions}`);
+ }
+ const ret = [undefined];
+ for (const val of [-9, -8, 0, 1, 7, 8]) {
+ const v = [];
+ for (let i = 0; i < numDimensions; ++i) {
+ v.push(val);
+ }
+ ret.push(v);
+ }
+ return ret;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupBarrier.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupBarrier.spec.js
new file mode 100644
index 0000000000..7bc3ecf3a4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/call/builtin/workgroupBarrier.spec.js
@@ -0,0 +1,39 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+'workgroupBarrier' affects memory and atomic operations in the workgroup address space.
+
+All synchronization functions execute a control barrier with Acquire/Release memory ordering.
+That is, all synchronization functions, and affected memory and atomic operations are ordered
+in program order relative to the synchronization function. Additionally, the affected memory
+and atomic operations program-ordered before the synchronization function must be visible to
+all other threads in the workgroup before any affected memory or atomic operation program-ordered
+after the synchronization function is executed by a member of the workgroup. All synchronization
+functions use the Workgroup memory scope. All synchronization functions have a Workgroup
+execution scope.
+
+All synchronization functions must only be used in the compute shader stage.
+`;
+import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('stage')
+ .specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions')
+ .desc(
+ `
+All synchronization functions must only be used in the compute shader stage.
+`
+ )
+ .params(u => u.combine('stage', ['vertex', 'fragment', 'compute']))
+ .unimplemented();
+
+g.test('barrier')
+ .specURL('https://www.w3.org/TR/WGSL/#sync-builtin-functions')
+ .desc(
+ `
+fn workgroupBarrier()
+`
+ )
+ .unimplemented();
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js
new file mode 100644
index 0000000000..dfa7a95738
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/case_cache.js
@@ -0,0 +1,144 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { dataCache } from '../../../../common/framework/data_cache.js';
+import { deserializeComparator } from '../../../util/compare.js';
+import { Scalar, Vector, serializeValue, deserializeValue } from '../../../util/conversion.js';
+import {
+ deserializeF32Interval,
+ F32Interval,
+ serializeF32Interval,
+} from '../../../util/f32_interval.js';
+
+/** serializeExpectation() converts an Expectation to a SerializedExpectation */
+export function serializeExpectation(e) {
+ if (e instanceof Scalar || e instanceof Vector) {
+ return { kind: 'value', value: serializeValue(e) };
+ }
+ if (e instanceof F32Interval) {
+ return { kind: 'interval', value: serializeF32Interval(e) };
+ }
+ if (e instanceof Array) {
+ return { kind: 'intervals', value: e.map(i => serializeF32Interval(i)) };
+ }
+ if (e instanceof Function) {
+ const comp = e;
+ if (comp !== undefined) {
+ // if blocks used to refine the type of comp.kind, otherwise it is
+ // actually the union of the string values
+ if (comp.kind === 'anyOf') {
+ return { kind: 'comparator', value: { kind: comp.kind, data: comp.data } };
+ }
+ if (comp.kind === 'skipUndefined') {
+ return { kind: 'comparator', value: { kind: comp.kind, data: comp.data } };
+ }
+ }
+ throw 'cannot serialize comparator';
+ }
+ throw 'cannot serialize expectation';
+}
+
+/** deserializeExpectation() converts a SerializedExpectation to a Expectation */
+export function deserializeExpectation(data) {
+ switch (data.kind) {
+ case 'value':
+ return deserializeValue(data.value);
+ case 'interval':
+ return deserializeF32Interval(data.value);
+ case 'intervals':
+ return data.value.map(i => deserializeF32Interval(i));
+ case 'comparator':
+ return deserializeComparator(data.value);
+ }
+}
+
+/**
+ * SerializedCase holds the serialized form of a Case.
+ * This form can be safely encoded to JSON.
+ */
+
+/** serializeCase() converts an Case to a SerializedCase */
+export function serializeCase(c) {
+ return {
+ input: c.input instanceof Array ? c.input.map(v => serializeValue(v)) : serializeValue(c.input),
+ expected: serializeExpectation(c.expected),
+ };
+}
+
+/** serializeCase() converts an SerializedCase to a Case */
+export function deserializeCase(data) {
+ return {
+ input:
+ data.input instanceof Array
+ ? data.input.map(v => deserializeValue(v))
+ : deserializeValue(data.input),
+ expected: deserializeExpectation(data.expected),
+ };
+}
+
+/** CaseListBuilder is a function that builds a CaseList */
+
+/**
+ * CaseCache is a cache of CaseList.
+ * CaseCache implements the Cacheable interface, so the cases can be pre-built
+ * and stored in the data cache, reducing computation costs at CTS runtime.
+ */
+export class CaseCache {
+ /**
+ * Constructor
+ * @param name the name of the cache. This must be globally unique.
+ * @param builders a Record of case-list name to case-list builder.
+ */
+ constructor(name, builders) {
+ this.path = `webgpu/shader/execution/case-cache/${name}.json`;
+ this.builders = builders;
+ }
+
+ /** get() returns the list of cases with the given name */
+ async get(name) {
+ const data = await dataCache.fetch(this);
+ return data[name];
+ }
+
+ /**
+ * build() implements the Cacheable.build interface.
+ * @returns the data.
+ */
+ build() {
+ const built = {};
+ for (const name in this.builders) {
+ const cases = this.builders[name]();
+ built[name] = cases;
+ }
+ return Promise.resolve(built);
+ }
+
+ /**
+ * serialize() implements the Cacheable.serialize interface.
+ * @returns the serialized data.
+ */
+ serialize(data) {
+ const serialized = {};
+ for (const name in data) {
+ serialized[name] = data[name].map(c => serializeCase(c));
+ }
+ return JSON.stringify(serialized);
+ }
+
+ /**
+ * deserialize() implements the Cacheable.deserialize interface.
+ * @returns the deserialize data.
+ */
+ deserialize(serialized) {
+ const data = JSON.parse(serialized);
+ const casesByName = {};
+ for (const name in data) {
+ const cases = data[name].map(caseData => deserializeCase(caseData));
+ casesByName[name] = cases;
+ }
+ return casesByName;
+ }
+}
+
+export function makeCaseCache(name, builders) {
+ return new CaseCache(name, builders);
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js
new file mode 100644
index 0000000000..eeef60ad2f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/expression.js
@@ -0,0 +1,988 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { globalTestConfig } from '../../../../common/framework/test_config.js';
+import { assert } from '../../../../common/util/util.js';
+import { compare, anyOf } from '../../../util/compare.js';
+import {
+ ScalarType,
+ Scalar,
+ TypeVec,
+ TypeU32,
+ Vector,
+ VectorType,
+ f32,
+ u32,
+ i32,
+} from '../../../util/conversion.js';
+import { F32Interval } from '../../../util/f32_interval.js';
+import { cartesianProduct, quantizeToF32, quantizeToU32 } from '../../../util/math.js';
+
+/** Is this expectation actually a Comparator */
+function isComparator(e) {
+ return !(
+ e instanceof F32Interval ||
+ e instanceof Scalar ||
+ e instanceof Vector ||
+ e instanceof Array
+ );
+}
+
+/** Helper for converting Values to Comparators */
+export function toComparator(input) {
+ if (!isComparator(input)) {
+ return got => compare(got, input);
+ }
+ return input;
+}
+
+/** Case is a single expression test case. */
+
+// Read-write storage buffer
+
+/** All possible input sources */
+export const allInputSources = ['const', 'uniform', 'storage_r', 'storage_rw'];
+
+/** Configuration for running a expression test */
+
+// Helper for returning the WGSL storage type for the given Type.
+function storageType(ty) {
+ if (ty instanceof ScalarType) {
+ if (ty.kind === 'bool') {
+ return TypeU32;
+ }
+ }
+ if (ty instanceof VectorType) {
+ return TypeVec(ty.width, storageType(ty.elementType));
+ }
+ return ty;
+}
+
+// Helper for converting a value of the type 'ty' from the storage type.
+function fromStorage(ty, expr) {
+ if (ty instanceof ScalarType) {
+ if (ty.kind === 'bool') {
+ return `${expr} != 0u`;
+ }
+ }
+ if (ty instanceof VectorType) {
+ if (ty.elementType.kind === 'bool') {
+ return `${expr} != vec${ty.width}<u32>(0u)`;
+ }
+ }
+ return expr;
+}
+
+// Helper for converting a value of the type 'ty' to the storage type.
+function toStorage(ty, expr) {
+ if (ty instanceof ScalarType) {
+ if (ty.kind === 'bool') {
+ return `select(0u, 1u, ${expr})`;
+ }
+ }
+ if (ty instanceof VectorType) {
+ if (ty.elementType.kind === 'bool') {
+ return `select(vec${ty.width}<u32>(0u), vec${ty.width}<u32>(1u), ${expr})`;
+ }
+ }
+ return expr;
+}
+
+// Currently all values are packed into buffers of 16 byte strides
+const kValueStride = 16;
+
+// ExpressionBuilder returns the WGSL used to test an expression.
+
+/**
+ * Searches for an entry with the given key, adding and returning the result of calling
+ * @p create if the entry was not found.
+ * @param map the cache map
+ * @param key the entry's key
+ * @param create the function used to construct a value, if not found in the cache
+ * @returns the value, either fetched from the cache, or newly built.
+ */
+function getOrCreate(map, key, create) {
+ const existing = map.get(key);
+ if (existing !== undefined) {
+ return existing;
+ }
+ const value = create();
+ map.set(key, value);
+ return value;
+}
+/**
+ * Runs the list of expression tests, possibly splitting the tests into multiple
+ * dispatches to keep the input data within the buffer binding limits.
+ * run() will pack the scalar test cases into smaller set of vectorized tests
+ * if `cfg.vectorize` is defined.
+ * @param t the GPUTest
+ * @param expressionBuilder the expression builder function
+ * @param parameterTypes the list of expression parameter types
+ * @param returnType the return type for the expression overload
+ * @param cfg test configuration values
+ * @param cases list of test cases
+ */
+export async function run(
+ t,
+ expressionBuilder,
+ parameterTypes,
+ returnType,
+ cfg = { inputSource: 'storage_r' },
+ cases
+) {
+ // If the 'vectorize' config option was provided, pack the cases into vectors.
+ if (cfg.vectorize !== undefined) {
+ const packed = packScalarsToVector(parameterTypes, returnType, cases, cfg.vectorize);
+ cases = packed.cases;
+ parameterTypes = packed.parameterTypes;
+ returnType = packed.returnType;
+ }
+
+ // The size of the input buffer may exceed the maximum buffer binding size,
+ // so chunk the tests up into batches that fit into the limits. We also split
+ // the cases into smaller batches to help with shader compilation performance.
+ const casesPerBatch = (function () {
+ switch (cfg.inputSource) {
+ case 'const':
+ // Some drivers are slow to optimize shaders with many constant values,
+ // or statements. 32 is an empirically picked number of cases that works
+ // well for most drivers.
+ return 32;
+ case 'uniform':
+ // Some drivers are slow to build pipelines with large uniform buffers.
+ // 2k appears to be a sweet-spot when benchmarking.
+ return Math.floor(
+ Math.min(1024 * 2, t.device.limits.maxUniformBufferBindingSize) /
+ (parameterTypes.length * kValueStride)
+ );
+
+ case 'storage_r':
+ case 'storage_rw':
+ return Math.floor(
+ t.device.limits.maxStorageBufferBindingSize / (parameterTypes.length * kValueStride)
+ );
+ }
+ })();
+
+ // A cache to hold built shader pipelines.
+ const pipelineCache = new Map();
+
+ // Submit all the cases in batches, each in a separate error scope.
+ const checkResults = [];
+ for (let i = 0; i < cases.length; i += casesPerBatch) {
+ const batchCases = cases.slice(i, Math.min(i + casesPerBatch, cases.length));
+
+ t.device.pushErrorScope('validation');
+
+ const checkBatch = submitBatch(
+ t,
+ expressionBuilder,
+ parameterTypes,
+ returnType,
+ batchCases,
+ cfg.inputSource,
+ pipelineCache
+ );
+
+ checkResults.push(
+ // Check GPU validation (shader compilation, pipeline creation, etc) before checking the batch results.
+ t.device.popErrorScope().then(error => {
+ if (error === null) {
+ checkBatch();
+ } else {
+ t.fail(error.message);
+ }
+ })
+ );
+ }
+
+ // Check the results
+ await Promise.all(checkResults);
+}
+
+/**
+ * Submits the list of expression tests. The input data must fit within the
+ * buffer binding limits of the given inputSource.
+ * @param t the GPUTest
+ * @param expressionBuilder the expression builder function
+ * @param parameterTypes the list of expression parameter types
+ * @param returnType the return type for the expression overload
+ * @param cases list of test cases that fit within the binding limits of the device
+ * @param inputSource the source of the input values
+ * @param pipelineCache the cache of compute pipelines, shared between batches
+ * @returns a function that checks the results are as expected
+ */
+function submitBatch(
+ t,
+ expressionBuilder,
+ parameterTypes,
+ returnType,
+ cases,
+ inputSource,
+ pipelineCache
+) {
+ // Construct a buffer to hold the results of the expression tests
+ const outputBufferSize = cases.length * kValueStride;
+ const outputBuffer = t.device.createBuffer({
+ size: outputBufferSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ });
+
+ const [pipeline, group] = buildPipeline(
+ t,
+ expressionBuilder,
+ parameterTypes,
+ returnType,
+ cases,
+ inputSource,
+ outputBuffer,
+ pipelineCache
+ );
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, group);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+
+ // Heartbeat to ensure CTS runners know we're alive.
+ globalTestConfig.testHeartbeatCallback();
+
+ t.queue.submit([encoder.finish()]);
+
+ // Return a function that can check the results of the shader
+ return () => {
+ const checkExpectation = outputData => {
+ // Read the outputs from the output buffer
+ const outputs = new Array(cases.length);
+ for (let i = 0; i < cases.length; i++) {
+ outputs[i] = returnType.read(outputData, i * kValueStride);
+ }
+
+ // The list of expectation failures
+ const errs = [];
+
+ // For each case...
+ for (let caseIdx = 0; caseIdx < cases.length; caseIdx++) {
+ const c = cases[caseIdx];
+ const got = outputs[caseIdx];
+ const cmp = toComparator(c.expected)(got);
+ if (!cmp.matched) {
+ errs.push(`(${c.input instanceof Array ? c.input.join(', ') : c.input})
+ returned: ${cmp.got}
+ expected: ${cmp.expected}`);
+ }
+ }
+
+ return errs.length > 0 ? new Error(errs.join('\n\n')) : undefined;
+ };
+
+ // Heartbeat to ensure CTS runners know we're alive.
+ globalTestConfig.testHeartbeatCallback();
+
+ t.expectGPUBufferValuesPassCheck(outputBuffer, checkExpectation, {
+ type: Uint8Array,
+ typedLength: outputBufferSize,
+ });
+ };
+}
+
+/**
+ * @param v either an array of T or a single element of type T
+ * @param i the value index to
+ * @returns the i'th value of v, if v is an array, otherwise v (i must be 0)
+ */
+function ith(v, i) {
+ if (v instanceof Array) {
+ assert(i < v.length);
+ return v[i];
+ }
+ assert(i === 0);
+ return v;
+}
+
+/**
+ * Constructs and returns a GPUComputePipeline and GPUBindGroup for running a
+ * batch of test cases. If a pre-created pipeline can be found in
+ * @p pipelineCache, then this may be returned instead of creating a new
+ * pipeline.
+ * @param t the GPUTest
+ * @param expressionBuilder the expression builder function
+ * @param parameterTypes the list of expression parameter types
+ * @param returnType the return type for the expression overload
+ * @param cases list of test cases that fit within the binding limits of the device
+ * @param inputSource the source of the input values
+ * @param outputBuffer the buffer that will hold the output values of the tests
+ * @param pipelineCache the cache of compute pipelines, shared between batches
+ */
+function buildPipeline(
+ t,
+ expressionBuilder,
+ parameterTypes,
+ returnType,
+ cases,
+ inputSource,
+ outputBuffer,
+ pipelineCache
+) {
+ // wgsl declaration of output buffer and binding
+ const wgslStorageType = storageType(returnType);
+ const wgslOutputs = `
+struct Output {
+ @size(${kValueStride}) value : ${wgslStorageType}
+};
+@group(0) @binding(0) var<storage, read_write> outputs : array<Output, ${cases.length}>;
+`;
+
+ switch (inputSource) {
+ case 'const': {
+ //////////////////////////////////////////////////////////////////////////
+ // Input values are constant values in the WGSL shader
+ //////////////////////////////////////////////////////////////////////////
+ const wgslValues = cases.map(c => {
+ const args = parameterTypes.map((_, i) => `(${ith(c.input, i).wgsl()})`);
+ return `${toStorage(returnType, expressionBuilder(args))}`;
+ });
+
+ const wgslBody = globalTestConfig.unrollConstEvalLoops
+ ? wgslValues.map((_, i) => `outputs[${i}].value = values[${i}];`).join('\n ')
+ : `for (var i = 0u; i < ${cases.length}; i++) {
+ outputs[i].value = values[i];
+ }`;
+
+ // the full WGSL shader source
+ const source = `
+${wgslOutputs}
+
+const values = array<${wgslStorageType}, ${cases.length}>(
+ ${wgslValues.join(',\n ')}
+);
+
+@compute @workgroup_size(1)
+fn main() {
+ ${wgslBody}
+}
+`;
+
+ // build the shader module
+ const module = t.device.createShaderModule({ code: source });
+
+ // build the pipeline
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: { module, entryPoint: 'main' },
+ });
+
+ // build the bind group
+ const group = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: outputBuffer } }],
+ });
+
+ return [pipeline, group];
+ }
+
+ case 'uniform':
+ case 'storage_r':
+ case 'storage_rw': {
+ //////////////////////////////////////////////////////////////////////////
+ // Input values come from a uniform or storage buffer
+ //////////////////////////////////////////////////////////////////////////
+
+ // returns the WGSL expression to load the ith parameter of the given type from the input buffer
+ const paramExpr = (ty, i) => fromStorage(ty, `inputs[i].param${i}`);
+
+ // resolves to the expression that calls the builtin
+ const expr = toStorage(returnType, expressionBuilder(parameterTypes.map(paramExpr)));
+
+ // input binding var<...> declaration
+ const wgslInputVar = (function () {
+ switch (inputSource) {
+ case 'storage_r':
+ return 'var<storage, read>';
+ case 'storage_rw':
+ return 'var<storage, read_write>';
+ case 'uniform':
+ return 'var<uniform>';
+ }
+ })();
+
+ // the full WGSL shader source
+ const source = `
+struct Input {
+${parameterTypes
+ .map((ty, i) => ` @size(${kValueStride}) param${i} : ${storageType(ty)},`)
+ .join('\n')}
+};
+
+${wgslOutputs}
+
+@group(0) @binding(1)
+${wgslInputVar} inputs : array<Input, ${cases.length}>;
+
+@compute @workgroup_size(1)
+fn main() {
+ for(var i = 0; i < ${cases.length}; i++) {
+ outputs[i].value = ${expr};
+ }
+}
+`;
+
+ // size in bytes of the input buffer
+ const inputSize = cases.length * parameterTypes.length * kValueStride;
+
+ // Holds all the parameter values for all cases
+ const inputData = new Uint8Array(inputSize);
+
+ // Pack all the input parameter values into the inputData buffer
+ {
+ const caseStride = kValueStride * parameterTypes.length;
+ for (let caseIdx = 0; caseIdx < cases.length; caseIdx++) {
+ const caseBase = caseIdx * caseStride;
+ for (let paramIdx = 0; paramIdx < parameterTypes.length; paramIdx++) {
+ const offset = caseBase + paramIdx * kValueStride;
+ const params = cases[caseIdx].input;
+ if (params instanceof Array) {
+ params[paramIdx].copyTo(inputData, offset);
+ } else {
+ params.copyTo(inputData, offset);
+ }
+ }
+ }
+ }
+
+ // build the compute pipeline, if the shader hasn't been compiled already.
+ const pipeline = getOrCreate(pipelineCache, source, () => {
+ // build the shader module
+ const module = t.device.createShaderModule({ code: source });
+
+ // build the pipeline
+ return t.device.createComputePipeline({
+ layout: 'auto',
+ compute: { module, entryPoint: 'main' },
+ });
+ });
+
+ // build the input buffer
+ const inputBuffer = t.makeBufferWithContents(
+ inputData,
+ GPUBufferUsage.COPY_SRC |
+ (inputSource === 'uniform' ? GPUBufferUsage.UNIFORM : GPUBufferUsage.STORAGE)
+ );
+
+ // build the bind group
+ const group = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ { binding: 0, resource: { buffer: outputBuffer } },
+ { binding: 1, resource: { buffer: inputBuffer } },
+ ],
+ });
+
+ return [pipeline, group];
+ }
+ }
+}
+
+/**
+ * Packs a list of scalar test cases into a smaller list of vector cases.
+ * Requires that all parameters of the expression overload are of a scalar type,
+ * and the return type of the expression overload is also a scalar type.
+ * If `cases.length` is not a multiple of `vectorWidth`, then the last scalar
+ * test case value is repeated to fill the vector value.
+ */
+function packScalarsToVector(parameterTypes, returnType, cases, vectorWidth) {
+ // Validate that the parameters and return type are all vectorizable
+ for (let i = 0; i < parameterTypes.length; i++) {
+ const ty = parameterTypes[i];
+ if (!(ty instanceof ScalarType)) {
+ throw new Error(
+ `packScalarsToVector() can only be used on scalar parameter types, but the ${i}'th parameter type is a ${ty}'`
+ );
+ }
+ }
+ if (!(returnType instanceof ScalarType)) {
+ throw new Error(
+ `packScalarsToVector() can only be used with a scalar return type, but the return type is a ${returnType}'`
+ );
+ }
+
+ const packedCases = [];
+ const packedParameterTypes = parameterTypes.map(p => TypeVec(vectorWidth, p));
+ const packedReturnType = new VectorType(vectorWidth, returnType);
+
+ const clampCaseIdx = idx => Math.min(idx, cases.length - 1);
+
+ let caseIdx = 0;
+ while (caseIdx < cases.length) {
+ // Construct the vectorized inputs from the scalar cases
+ const packedInputs = new Array(parameterTypes.length);
+ for (let paramIdx = 0; paramIdx < parameterTypes.length; paramIdx++) {
+ const inputElements = new Array(vectorWidth);
+ for (let i = 0; i < vectorWidth; i++) {
+ const input = cases[clampCaseIdx(caseIdx + i)].input;
+ inputElements[i] = input instanceof Array ? input[paramIdx] : input;
+ }
+ packedInputs[paramIdx] = new Vector(inputElements);
+ }
+
+ // Gather the comparators for the packed cases
+ const comparators = new Array(vectorWidth);
+ for (let i = 0; i < vectorWidth; i++) {
+ comparators[i] = toComparator(cases[clampCaseIdx(caseIdx + i)].expected);
+ }
+ const packedComparator = got => {
+ let matched = true;
+ const gElements = new Array(vectorWidth);
+ const eElements = new Array(vectorWidth);
+ for (let i = 0; i < vectorWidth; i++) {
+ const d = comparators[i](got.elements[i]);
+ matched = matched && d.matched;
+ gElements[i] = d.got;
+ eElements[i] = d.expected;
+ }
+ return {
+ matched,
+ got: `${packedReturnType}(${gElements.join(', ')})`,
+ expected: `${packedReturnType}(${eElements.join(', ')})`,
+ };
+ };
+
+ // Append the new packed case
+ packedCases.push({ input: packedInputs, expected: packedComparator });
+ caseIdx += vectorWidth;
+ }
+
+ return {
+ cases: packedCases,
+ parameterTypes: packedParameterTypes,
+ returnType: packedReturnType,
+ };
+}
+
+/**
+ * Indicates bounds that acceptance intervals need to be within to avoid inputs
+ * being filtered out. This is used for const-eval tests, since going OOB will
+ * cause a validation error not an execution error.
+ */
+
+// No expectations
+
+/**
+ * @returns a Case for the param and unary interval generator provided
+ * The Case will use use an interval comparator for matching results.
+ * @param param the param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for an
+ * unary operation
+ */
+function makeUnaryToF32IntervalCase(param, filter, ...ops) {
+ param = quantizeToF32(param);
+
+ const intervals = ops.map(o => o(param));
+ if (filter === 'f32-only' && intervals.some(i => !i.isFinite())) {
+ return undefined;
+ }
+ return { input: [f32(param)], expected: anyOf(...intervals) };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param params array of inputs to try
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for an
+ * unary operation
+ */
+export function generateUnaryToF32IntervalCases(params, filter, ...ops) {
+ return params.reduce((cases, e) => {
+ const c = makeUnaryToF32IntervalCase(e, filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the params and binary interval generator provided
+ * The Case will use use an interval comparator for matching results.
+ * @param param0 the first param or left hand side to pass in
+ * @param param1 the second param or rhs hand side to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * binary operation
+ */
+function makeBinaryToF32IntervalCase(param0, param1, filter, ...ops) {
+ param0 = quantizeToF32(param0);
+ param1 = quantizeToF32(param1);
+
+ const intervals = ops.map(o => o(param0, param1));
+ if (filter === 'f32-only' && intervals.some(i => !i.isFinite())) {
+ return undefined;
+ }
+ return { input: [f32(param0), f32(param1)], expected: anyOf(...intervals) };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first param
+ * @param param1s array of inputs to try for the second param
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * binary operation
+ */
+export function generateBinaryToF32IntervalCases(param0s, param1s, filter, ...ops) {
+ return cartesianProduct(param0s, param1s).reduce((cases, e) => {
+ const c = makeBinaryToF32IntervalCase(e[0], e[1], filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the params and ternary interval generator provided
+ * The Case will use use an interval comparator for matching results.
+ * @param param0 the first param to pass in
+ * @param param1 the second param to pass in
+ * @param param2 the third param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * ternary operation.
+ */
+function makeTernaryToF32IntervalCase(param0, param1, param2, filter, ...ops) {
+ param0 = quantizeToF32(param0);
+ param1 = quantizeToF32(param1);
+ param2 = quantizeToF32(param2);
+
+ const intervals = ops.map(o => o(param0, param1, param2));
+ if (filter === 'f32-only' && intervals.some(i => !i.isFinite())) {
+ return undefined;
+ }
+ return {
+ input: [f32(param0), f32(param1), f32(param2)],
+ expected: anyOf(...intervals),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first param
+ * @param param1s array of inputs to try for the second param
+ * @param param2s array of inputs to try for the third param
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * ternary operation.
+ */
+export function generateTernaryToF32IntervalCases(param0s, param1s, param2s, filter, ...ops) {
+ return cartesianProduct(param0s, param1s, param2s).reduce((cases, e) => {
+ const c = makeTernaryToF32IntervalCase(e[0], e[1], e[2], filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the param and vector interval generator provided
+ * @param param the param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * vector.
+ */
+function makeVectorToF32IntervalCase(param, filter, ...ops) {
+ param = param.map(quantizeToF32);
+ const param_f32 = param.map(f32);
+
+ const intervals = ops.map(o => o(param));
+ if (filter === 'f32-only' && intervals.some(i => !i.isFinite())) {
+ return undefined;
+ }
+ return {
+ input: [new Vector(param_f32)],
+ expected: anyOf(...intervals),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param params array of inputs to try
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * vector.
+ */
+export function generateVectorToF32IntervalCases(params, filter, ...ops) {
+ return params.reduce((cases, e) => {
+ const c = makeVectorToF32IntervalCase(e, filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the params and vector pair interval generator provided
+ * @param param0 the first param to pass in
+ * @param param1 the second param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * pair of vectors.
+ */
+function makeVectorPairToF32IntervalCase(param0, param1, filter, ...ops) {
+ param0 = param0.map(quantizeToF32);
+ param1 = param1.map(quantizeToF32);
+ const param0_f32 = param0.map(f32);
+ const param1_f32 = param1.map(f32);
+
+ const intervals = ops.map(o => o(param0, param1));
+ if (filter === 'f32-only' && intervals.some(i => !i.isFinite())) {
+ return undefined;
+ }
+ return {
+ input: [new Vector(param0_f32), new Vector(param1_f32)],
+ expected: anyOf(...intervals),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first input
+ * @param param1s array of inputs to try for the second input
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance interval for a
+ * pair of vectors.
+ */
+export function generateVectorPairToF32IntervalCases(param0s, param1s, filter, ...ops) {
+ return cartesianProduct(param0s, param1s).reduce((cases, e) => {
+ const c = makeVectorPairToF32IntervalCase(e[0], e[1], filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the param and vector of intervals generator provided
+ * @param param the param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an vector of acceptance
+ * intervals for a vector.
+ */
+function makeVectorToVectorCase(param, filter, ...ops) {
+ param = param.map(quantizeToF32);
+ const param_f32 = param.map(f32);
+
+ const vectors = ops.map(o => o(param));
+ if (filter === 'f32-only' && vectors.some(v => !v.every(e => e.isFinite()))) {
+ return undefined;
+ }
+ return {
+ input: [new Vector(param_f32)],
+ expected: anyOf(...vectors),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param params array of inputs to try
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an vector of acceptance
+ * intervals for a vector.
+ */
+export function generateVectorToVectorCases(params, filter, ...ops) {
+ return params.reduce((cases, e) => {
+ const c = makeVectorToVectorCase(e, filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the params and vector of intervals generator provided
+ * @param param0 the first param to pass in
+ * @param param1 the second param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an vector of acceptance
+ * intervals for a pair of vectors.
+ */
+function makeVectorPairToVectorCase(param0, param1, filter, ...ops) {
+ param0 = param0.map(quantizeToF32);
+ param1 = param1.map(quantizeToF32);
+ const param0_f32 = param0.map(f32);
+ const param1_f32 = param1.map(f32);
+
+ const vectors = ops.map(o => o(param0, param1));
+ if (filter === 'f32-only' && vectors.some(v => !v.every(e => e.isFinite()))) {
+ return undefined;
+ }
+ return {
+ input: [new Vector(param0_f32), new Vector(param1_f32)],
+ expected: anyOf(...vectors),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first input
+ * @param param1s array of inputs to try for the second input
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an vector of acceptance
+ * intervals for a pair of vectors.
+ */
+export function generateVectorPairToVectorCases(param0s, param1s, filter, ...ops) {
+ return cartesianProduct(param0s, param1s).reduce((cases, e) => {
+ const c = makeVectorPairToVectorCase(e[0], e[1], filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns a Case for the param and vector of intervals generator provided
+ * The input is treated as an unsigned int.
+ * @param param the param to pass in
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance
+ * interval for an unsigned int.
+ */
+function makeU32ToVectorCase(param, filter, ...ops) {
+ param = Math.trunc(param);
+ const param_u32 = u32(param);
+
+ const vectors = ops.map(o => o(param));
+ if (filter === 'f32-only' && vectors.some(v => !v.every(e => e.isFinite()))) {
+ return undefined;
+ }
+ return {
+ input: param_u32,
+ expected: anyOf(...vectors),
+ };
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * The input is treated as an unsigned int.
+ * @param params array of inputs to try
+ * @param filter what interval filtering to apply
+ * @param ops callbacks that implement generating an acceptance
+ * interval for an unsigned int.
+ */
+export function generateU32ToVectorCases(params, filter, ...ops) {
+ return params.reduce((cases, e) => {
+ const c = makeU32ToVectorCase(e, filter, ...ops);
+ if (c !== undefined) {
+ cases.push(c);
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * A function that performs a binary operation on x and y, and returns the expected
+ * result, or undefined if the operation is invalid for the given inputs.
+ */
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first param
+ * @param param1s array of inputs to try for the second param
+ * @param op callback called on each pair of inputs to produce each case
+ */
+export function generateBinaryToI32Cases(params0s, params1s, op) {
+ return cartesianProduct(params0s, params1s).reduce((cases, e) => {
+ const expected = op(e[0], e[1]);
+ if (expected !== undefined) {
+ cases.push({ input: [i32(e[0]), i32(e[1])], expected: i32(expected) });
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * @returns an array of Cases for operations over a range of inputs
+ * @param param0s array of inputs to try for the first param
+ * @param param1s array of inputs to try for the second param
+ * @param op callback called on each pair of inputs to produce each case
+ */
+export function generateBinaryToU32Cases(params0s, params1s, op) {
+ return cartesianProduct(params0s, params1s).reduce((cases, e) => {
+ const expected = op(e[0], e[1]);
+ if (expected !== undefined) {
+ cases.push({ input: [u32(e[0]), u32(e[1])], expected: u32(expected) });
+ }
+ return cases;
+ }, new Array());
+}
+
+/**
+ * A function that performs a binary operation on x and y, and returns the expected
+ * result.
+ */
+
+/**
+ * @returns a Case for the input params with op applied
+ * @param scalar scalar param
+ * @param vector vector param (2, 3, or 4 elements)
+ * @param op the op to apply to scalar and vector
+ */
+function makeU32VectorBinaryToVectorCase(scalar, vector, op) {
+ scalar = quantizeToU32(scalar);
+ vector = vector.map(quantizeToU32);
+ const result = new Vector(vector.map(v => u32(op(scalar, v))));
+ return {
+ input: [u32(scalar), new Vector(vector.map(u32))],
+ expected: result,
+ };
+}
+
+/**
+ * @returns array of Case for the input params with op applied
+ * @param scalars array of scalar params
+ * @param vectors array of vector params (2, 3, or 4 elements)
+ * @param op he op to apply to each pair of scalar and vector
+ */
+export function generateU32VectorBinaryToVectorCases(scalars, vectors, op) {
+ return scalars.flatMap(s => {
+ return vectors.map(v => {
+ return makeU32VectorBinaryToVectorCase(s, v, op);
+ });
+ });
+}
+
+/**
+ * @returns a Case for the input params with op applied
+ * @param vector vector param (2, 3, or 4 elements)
+ * @param scalar scalar param
+ * @param op the op to apply to vector and scalar
+ */
+function makeVectorU32BinaryToVectorCase(vector, scalar, op) {
+ vector = vector.map(quantizeToU32);
+ scalar = quantizeToU32(scalar);
+ const result = new Vector(vector.map(v => u32(op(v, scalar))));
+ return {
+ input: [new Vector(vector.map(u32)), u32(scalar)],
+ expected: result,
+ };
+}
+
+/**
+ * @returns array of Case for the input params with op applied
+ * @param vectors array of vector params (2, 3, or 4 elements)
+ * @param scalars array of scalar params
+ * @param op he op to apply to each pair of vector and scalar
+ */
+export function generateVectorU32BinaryToVectorCases(vectors, scalars, op) {
+ return scalars.flatMap(s => {
+ return vectors.map(v => {
+ return makeVectorU32BinaryToVectorCase(v, s, op);
+ });
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js
new file mode 100644
index 0000000000..fb281d04b5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/bool_logical.spec.js
@@ -0,0 +1,32 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the boolean unary logical expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { bool, TypeBool } from '../../../../util/conversion.js';
+import { allInputSources, run } from '../expression.js';
+
+import { unary } from './unary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('negation')
+ .specURL('https://www.w3.org/TR/WGSL/#logical-expr')
+ .desc(
+ `
+Expression: !e
+
+Logical negation. The result is true when e is false and false when e is true. Component-wise when T is a vector.
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = [
+ { input: bool(true), expected: bool(false) },
+ { input: bool(false), expected: bool(true) },
+ ];
+
+ await run(t, unary('!'), [TypeBool], TypeBool, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js
new file mode 100644
index 0000000000..784e6eaa1c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/f32_arithmetic.spec.js
@@ -0,0 +1,40 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the f32 arithmetic unary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { TypeF32 } from '../../../../util/conversion.js';
+import { negationInterval } from '../../../../util/f32_interval.js';
+import { fullF32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import { allInputSources, generateUnaryToF32IntervalCases, run } from '../expression.js';
+
+import { unary } from './unary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unary/f32_arithmetic', {
+ negation: () => {
+ return generateUnaryToF32IntervalCases(
+ fullF32Range({ neg_norm: 250, neg_sub: 20, pos_sub: 20, pos_norm: 250 }),
+ 'unfiltered',
+ negationInterval
+ );
+ },
+});
+
+g.test('negation')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: -x
+Accuracy: Correctly rounded
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('negation');
+ await run(t, unary('-'), [TypeF32], TypeF32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js
new file mode 100644
index 0000000000..d2afcec3ac
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/i32_arithmetic.spec.js
@@ -0,0 +1,36 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for the i32 arithmetic unary expression operations
+`;
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../../gpu_test.js';
+import { i32, TypeI32 } from '../../../../util/conversion.js';
+import { fullI32Range } from '../../../../util/math.js';
+import { makeCaseCache } from '../case_cache.js';
+import { allInputSources, run } from '../expression.js';
+
+import { unary } from './unary.js';
+
+export const g = makeTestGroup(GPUTest);
+
+export const d = makeCaseCache('unary/i32_arithmetic', {
+ negation: () => {
+ return fullI32Range().map(e => {
+ return { input: i32(e), expected: i32(-e) };
+ });
+ },
+});
+
+g.test('negation')
+ .specURL('https://www.w3.org/TR/WGSL/#floating-point-evaluation')
+ .desc(
+ `
+Expression: -x
+`
+ )
+ .params(u => u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4]))
+ .fn(async t => {
+ const cases = await d.get('negation');
+ await run(t, unary('-'), [TypeI32], TypeI32, t.params, cases);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js
new file mode 100644
index 0000000000..b80072a985
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/expression/unary/unary.js
@@ -0,0 +1,6 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /* @returns an ExpressionBuilder that evaluates a prefix unary operation */
+export function unary(op) {
+ return value => `${op}(${value})`;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/atomicity.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/atomicity.spec.js
new file mode 100644
index 0000000000..0286cf42d5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/atomicity.spec.js
@@ -0,0 +1,103 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Tests for the atomicity of atomic read-modify-write instructions.`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+import {
+ MemoryModelTester,
+ buildTestShader,
+ TestType,
+ buildResultShader,
+ ResultType,
+ MemoryType,
+} from './memory_model_setup.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// A reasonable parameter set, determined heuristically.
+const memoryModelTestParams = {
+ workgroupSize: 256,
+ testingWorkgroups: 512,
+ maxWorkgroups: 1024,
+ shufflePct: 100,
+ barrierPct: 100,
+ memStressPct: 100,
+ memStressIterations: 1024,
+ memStressStoreFirstPct: 50,
+ memStressStoreSecondPct: 50,
+ preStressPct: 100,
+ preStressIterations: 1024,
+ preStressStoreFirstPct: 50,
+ preStressStoreSecondPct: 50,
+ scratchMemorySize: 2048,
+ stressLineSize: 64,
+ stressTargetLines: 2,
+ stressStrategyBalancePct: 50,
+ permuteFirst: 109,
+ permuteSecond: 419,
+ memStride: 4,
+ aliasedMemory: false,
+ numBehaviors: 4,
+};
+
+const storageMemoryTestCode = `
+ let r0 = atomicAdd(&test_locations.value[x_0], 0u);
+ atomicStore(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupMemoryTestCode = `
+ let r0 = atomicAdd(&wg_test_locations[x_0], 0u);
+ atomicStore(&wg_test_locations[x_1], 2u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+const resultCode = `
+ if ((r0 == 0u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 2u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+`;
+
+g.test('atomicity')
+ .desc(
+ `Checks whether a store on one thread can interrupt an atomic RMW on a second thread. If the read returned by
+ the RMW instruction is the initial value of memory (0), but the final value in memory is 1, then the atomic write
+ in the second thread occurred in between the read and the write of the RMW.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: storageMemoryTestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryTestCode,
+ },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.FourBehavior);
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(10, 3);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js
new file mode 100644
index 0000000000..dbf90149e3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/barrier.spec.js
@@ -0,0 +1,220 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for non-atomic memory synchronization within a workgroup in the presence of a WebGPU barrier`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+import {
+ MemoryModelTester,
+ buildTestShader,
+ MemoryType,
+ TestType,
+ buildResultShader,
+ ResultType,
+} from './memory_model_setup.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// A reasonable parameter set, determined heuristically.
+const memoryModelTestParams = {
+ workgroupSize: 256,
+ testingWorkgroups: 512,
+ maxWorkgroups: 1024,
+ shufflePct: 100,
+ barrierPct: 100,
+ memStressPct: 100,
+ memStressIterations: 1024,
+ memStressStoreFirstPct: 50,
+ memStressStoreSecondPct: 50,
+ preStressPct: 100,
+ preStressIterations: 1024,
+ preStressStoreFirstPct: 50,
+ preStressStoreSecondPct: 50,
+ scratchMemorySize: 2048,
+ stressLineSize: 64,
+ stressTargetLines: 2,
+ stressStrategyBalancePct: 50,
+ permuteFirst: 109,
+ permuteSecond: 419,
+ memStride: 4,
+ aliasedMemory: false,
+ numBehaviors: 2,
+};
+
+const storageMemoryBarrierStoreLoadTestCode = `
+ test_locations.value[x_0] = 1u;
+ workgroupBarrier();
+ let r0 = test_locations.value[x_1];
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+`;
+
+const workgroupMemoryBarrierStoreLoadTestCode = `
+ wg_test_locations[x_0] = 1u;
+ workgroupBarrier();
+ let r0 = wg_test_locations[x_1];
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+`;
+
+g.test('workgroup_barrier_store_load')
+ .desc(
+ `Checks whether the workgroup barrier properly synchronizes a non-atomic write and read on
+ separate threads in the same workgroup. Within a workgroup, the barrier should force an invocation
+ after the barrier to read a write from an invocation before the barrier.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.NonAtomicStorageClass, _testCode: storageMemoryBarrierStoreLoadTestCode },
+ {
+ memType: MemoryType.NonAtomicWorkgroupClass,
+ _testCode: workgroupMemoryBarrierStoreLoadTestCode,
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if (r0 == 1u) {
+ atomicAdd(&test_results.seq, 1u);
+ } else if (r0 == 0u) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const resultShader = buildResultShader(
+ resultCode,
+ TestType.IntraWorkgroup,
+ ResultType.TwoBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(15, 1);
+ });
+
+const storageMemoryBarrierLoadStoreTestCode = `
+ let r0 = test_locations.value[x_0];
+ workgroupBarrier();
+ test_locations.value[x_1] = 1u;
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const workgroupMemoryBarrierLoadStoreTestCode = `
+ let r0 = wg_test_locations[x_0];
+ workgroupBarrier();
+ wg_test_locations[x_1] = 1u;
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+g.test('workgroup_barrier_load_store')
+ .desc(
+ `Checks whether the workgroup barrier properly synchronizes a non-atomic write and read on
+ separate threads in the same workgroup. Within a workgroup, the barrier should force an invocation
+ before the barrier to not read the write from an invocation after the barrier.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.NonAtomicStorageClass, _testCode: storageMemoryBarrierLoadStoreTestCode },
+ {
+ memType: MemoryType.NonAtomicWorkgroupClass,
+ _testCode: workgroupMemoryBarrierLoadStoreTestCode,
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if (r0 == 0u) {
+ atomicAdd(&test_results.seq, 1u);
+ } else if (r0 == 1u) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const resultShader = buildResultShader(
+ resultCode,
+ TestType.IntraWorkgroup,
+ ResultType.TwoBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(12, 1);
+ });
+
+const storageMemoryBarrierStoreStoreTestCode = `
+ test_locations.value[x_0] = 1u;
+ storageBarrier();
+ test_locations.value[x_1] = 2u;
+`;
+
+const workgroupMemoryBarrierStoreStoreTestCode = `
+ wg_test_locations[x_0] = 1u;
+ workgroupBarrier();
+ wg_test_locations[x_1] = 2u;
+ workgroupBarrier();
+ test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1] = wg_test_locations[x_1];
+`;
+
+g.test('workgroup_barrier_store_store')
+ .desc(
+ `Checks whether the workgroup barrier properly synchronizes non-atomic writes on
+ separate threads in the same workgroup. Within a workgroup, the barrier should force the value in memory
+ to be the result of the write after the barrier, not the write before.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.NonAtomicStorageClass,
+ _testCode: storageMemoryBarrierStoreStoreTestCode,
+ },
+ {
+ memType: MemoryType.NonAtomicWorkgroupClass,
+ _testCode: workgroupMemoryBarrierStoreStoreTestCode,
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if (mem_x_0 == 2u) {
+ atomicAdd(&test_results.seq, 1u);
+ } else if (mem_x_0 == 1u) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const resultShader = buildResultShader(
+ resultCode,
+ TestType.IntraWorkgroup,
+ ResultType.TwoBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(10, 1);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/coherence.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/coherence.spec.js
new file mode 100644
index 0000000000..00dca4f9c7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/coherence.spec.js
@@ -0,0 +1,528 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests that all threads see a sequentially consistent view of the order of memory
+accesses to a single memory location. Uses a parallel testing strategy along with stressing
+threads to increase coverage of possible bugs.`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+import {
+ MemoryModelTester,
+ buildTestShader,
+ MemoryType,
+ TestType,
+ buildResultShader,
+ ResultType,
+} from './memory_model_setup.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// A reasonable parameter set, determined heuristically.
+const memoryModelTestParams = {
+ workgroupSize: 256,
+ testingWorkgroups: 39,
+ maxWorkgroups: 952,
+ shufflePct: 0,
+ barrierPct: 0,
+ memStressPct: 0,
+ memStressIterations: 1024,
+ memStressStoreFirstPct: 50,
+ memStressStoreSecondPct: 50,
+ preStressPct: 0,
+ preStressIterations: 1024,
+ preStressStoreFirstPct: 50,
+ preStressStoreSecondPct: 50,
+ scratchMemorySize: 2048,
+ stressLineSize: 64,
+ stressTargetLines: 2,
+ stressStrategyBalancePct: 50,
+ permuteFirst: 109,
+ permuteSecond: 1,
+ memStride: 1,
+ aliasedMemory: true,
+ numBehaviors: 4,
+};
+
+const storageMemoryCorrTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[x_1]);
+ let r1 = atomicLoad(&test_locations.value[y_1]);
+ atomicStore(&results.value[id_1].r0, r0);
+ atomicStore(&results.value[id_1].r1, r1);
+`;
+
+const workgroupStorageMemoryCorrTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[x_1]);
+ let r1 = atomicLoad(&test_locations.value[y_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const storageMemoryCorrRMWTestCode = `
+ atomicExchange(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[x_1]);
+ let r1 = atomicAdd(&test_locations.value[y_1], 0u);
+ atomicStore(&results.value[id_1].r0, r0);
+ atomicStore(&results.value[id_1].r1, r1);
+`;
+
+const workgroupStorageMemoryCorrRMWTestCode = `
+ atomicExchange(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[x_1]);
+ let r1 = atomicAdd(&test_locations.value[y_1], 0u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const workgroupMemoryCorrTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ let r0 = atomicLoad(&wg_test_locations[x_1]);
+ let r1 = atomicLoad(&wg_test_locations[y_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const workgroupMemoryCorrRMWTestCode = `
+ atomicExchange(&wg_test_locations[x_0], 1u);
+ let r0 = atomicLoad(&wg_test_locations[x_1]);
+ let r1 = atomicAdd(&wg_test_locations[y_1], 0u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+g.test('corr')
+ .desc(
+ `Ensures two reads on one thread cannot observe an inconsistent view of a write on a second thread.
+ The first thread writes the value 1 some location x, and the second thread reads x twice in a row.
+ If the first read returns 1 but the second read returns 0, then there has been a coherence violation.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCorrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCorrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCorrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCorrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCorrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCorrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if ((r0 == 0u && r1 == 0u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 1u && r1 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && r1 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 1u && r1 == 0u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.FourBehavior);
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(60, 3);
+ });
+
+const storageMemoryCowwTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ atomicStore(&test_locations.value[y_0], 2u);
+`;
+
+const storageMemoryCowwRMWTestCode = `
+ atomicExchange(&test_locations.value[x_0], 1u);
+ atomicStore(&test_locations.value[y_0], 2u);
+`;
+
+const workgroupMemoryCowwTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ atomicStore(&wg_test_locations[y_0], 2u);
+ workgroupBarrier();
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_0], atomicLoad(&wg_test_locations[x_0]));
+`;
+
+const workgroupMemoryCowwRMWTestCode = `
+ atomicExchange(&wg_test_locations[x_0], 1u);
+ atomicStore(&wg_test_locations[y_0], 2u);
+ workgroupBarrier();
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_0], atomicLoad(&wg_test_locations[x_0]));
+`;
+
+g.test('coww')
+ .desc(
+ `Ensures two writes on one thread do not lead to incoherent results. The thread first writes 1 to
+ some location x and then writes 2 to the same location. If the value in memory after the test finishes
+ is 1, then there has been a coherence violation.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCowwTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCowwRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: storageMemoryCowwTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: storageMemoryCowwRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCowwTestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCowwRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if (mem_x_0 == 2u) {
+ atomicAdd(&test_results.seq, 1u);
+ } else if (mem_x_0 == 1u) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.TwoBehavior);
+ const params = {
+ ...memoryModelTestParams,
+ numBehaviors: 2,
+ };
+ const memModelTester = new MemoryModelTester(t, params, testShader, resultShader);
+ await memModelTester.run(60, 1);
+ });
+
+const storageMemoryCowrTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[y_0]);
+ atomicStore(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupStorageMemoryCowrTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[y_0]);
+ atomicStore(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const storageMemoryCowrRMWTestCode = `
+ atomicExchange(&test_locations.value[x_0], 1u);
+ let r0 = atomicAdd(&test_locations.value[y_0], 0u);
+ atomicExchange(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupStorageMemoryCowrRMWTestCode = `
+ atomicExchange(&test_locations.value[x_0], 1u);
+ let r0 = atomicAdd(&test_locations.value[y_0], 0u);
+ atomicExchange(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const workgroupMemoryCowrTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ let r0 = atomicLoad(&wg_test_locations[y_0]);
+ atomicStore(&wg_test_locations[x_1], 2u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+const workgroupMemoryCowrRMWTestCode = `
+ atomicExchange(&wg_test_locations[x_0], 1u);
+ let r0 = atomicAdd(&wg_test_locations[y_0], 0u);
+ atomicExchange(&wg_test_locations[x_1], 2u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+g.test('cowr')
+ .desc(
+ `The first thread first writes 1 to some location x and then reads x. The second thread writes 2 to x.
+ If the first thread reads the value 2 and the value in memory at the end of the test is 1, then the read
+ and write on the first thread have been reordered, a coherence violation.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCowrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCowrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCowrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCowrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCowrTestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCowrRMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if ((r0 == 1u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 1u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 2u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 2u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.FourBehavior);
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(60, 3);
+ });
+
+const storageMemoryCorw1TestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[x_0], 1u);
+ workgroupBarrier();
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupStorageMemoryCorw1TestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[y_0], 1u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const workgroupMemoryCorw1TestCode = `
+ let r0 = atomicLoad(&wg_test_locations[x_0]);
+ atomicStore(&wg_test_locations[y_0], 1u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+g.test('corw1')
+ .desc(
+ `One thread first reads from a memory location x and then writes 1 to x. If the read observes the subsequent
+ write, there has been a coherence violation.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCorw1TestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCorw1TestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCorw1TestCode,
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if (r0 == 0u) {
+ atomicAdd(&test_results.seq, 1u);
+ } else if (r0 == 1u) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.TwoBehavior);
+ const params = {
+ ...memoryModelTestParams,
+ numBehaviors: 2,
+ };
+ const memModelTester = new MemoryModelTester(t, params, testShader, resultShader);
+ await memModelTester.run(60, 1);
+ });
+
+const storageMemoryCorw2TestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[y_0], 1u);
+ atomicStore(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupStorageMemoryCorw2TestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[y_0], 1u);
+ atomicStore(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const storageMemoryCorw2RMWTestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[y_0], 1u);
+ atomicExchange(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[id_0].r0, r0);
+`;
+
+const workgroupStorageMemoryCorw2RMWTestCode = `
+ let r0 = atomicLoad(&test_locations.value[x_0]);
+ atomicStore(&test_locations.value[y_0], 1u);
+ atomicExchange(&test_locations.value[x_1], 2u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+`;
+
+const workgroupMemoryCorw2TestCode = `
+ let r0 = atomicLoad(&wg_test_locations[x_0]);
+ atomicStore(&wg_test_locations[y_0], 1u);
+ atomicStore(&wg_test_locations[x_1], 2u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+const workgroupMemoryCorw2RMWTestCode = `
+ let r0 = atomicLoad(&wg_test_locations[x_0]);
+ atomicStore(&wg_test_locations[y_0], 1u);
+ atomicExchange(&wg_test_locations[x_1], 2u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+g.test('corw2')
+ .desc(
+ `The first thread reads from some memory location x, and then writes 1 to x. The second thread
+ writes 2 to x. If the first thread reads the value 2, but the value in memory after the test
+ completes is 1, then the instructions on the first thread have been re-ordered, leading to a
+ coherence violation.
+ `
+ )
+ .paramsSimple([
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCorw2TestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.InterWorkgroup,
+ _testCode: storageMemoryCorw2RMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCorw2TestCode,
+ },
+ {
+ memType: MemoryType.AtomicStorageClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupStorageMemoryCorw2RMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCorw2TestCode,
+ },
+ {
+ memType: MemoryType.AtomicWorkgroupClass,
+ testType: TestType.IntraWorkgroup,
+ _testCode: workgroupMemoryCorw2RMWTestCode,
+ extraFlags: 'rmw_variant',
+ },
+ ])
+ .fn(async t => {
+ const resultCode = `
+ if ((r0 == 0u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 2u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 2u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `;
+ const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType);
+ const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.FourBehavior);
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ resultShader
+ );
+
+ await memModelTester.run(60, 3);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js
new file mode 100644
index 0000000000..d0daa9a8f3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/memory_model_setup.js
@@ -0,0 +1,962 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { checkElementsPassPredicate } from '../../../util/check_contents.js';
+/* All buffer sizes are counted in units of 4-byte words. */
+
+/* Parameter values are set heuristically, typically by a time-intensive search. */
+
+/** The number of memory locations accessed by a test. Currently, only tests with up to 2 memory locations are supported. */
+const numMemLocations = 2;
+
+/** The number of read outputs per test that need to be analyzed in the result aggregation shader. Currently, only tests with up to 2 read outputs are supported. */
+const numReadOutputs = 2;
+
+/** Represents a device buffer and a utility buffer for resetting memory and copying parameters. */
+
+/** The number of stress params to add to the stress params buffer. */
+const numStressParams = 12;
+const barrierParamIndex = 0;
+const memStressIndex = 1;
+const memStressIterationsIndex = 2;
+const memStressPatternIndex = 3;
+const preStressIndex = 4;
+const preStressIterationsIndex = 5;
+const preStressPatternIndex = 6;
+const permuteFirstIndex = 7;
+const permuteSecondIndex = 8;
+const testingWorkgroupsIndex = 9;
+const memStrideIndex = 10;
+const memLocationOffsetIndex = 11;
+
+/**
+ * All memory used in these consists of a four byte word, so this value is used to correctly set the byte size of buffers that
+ * are read to/written from during tests and for storing test results.
+ */
+const bytesPerWord = 4;
+
+/**
+ * Implements setup code necessary to run a memory model test. A test consists of two parts:
+ * 1.) A test shader that runs a specified memory model litmus test and attempts to reveal a weak (disallowed) behavior.
+ * At a high level, a test shader consists of a set of testing workgroups where every invocation executes the litmus test
+ * on a set of test locations, and a set of stressing workgroups where every invocation accesses a specified memory location
+ * in a random pattern.
+ * 2.) A result shader that takes the output of the test shader, which consists of the memory locations accessed during the test
+ * and the results of any reads made during the test, and aggregate the results based on the possible behaviors of the test.
+ */
+export class MemoryModelTester {
+ /** Sets up a memory model test by initializing buffers and pipeline layouts. */
+ constructor(t, params, testShader, resultShader) {
+ this.test = t;
+ this.params = params;
+
+ // set up buffers
+ const testingThreads = this.params.workgroupSize * this.params.testingWorkgroups;
+ const testLocationsSize =
+ testingThreads * numMemLocations * this.params.memStride * bytesPerWord;
+ const testLocationsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: testLocationsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.makeBufferWithContents(
+ new Uint32Array(testLocationsSize).fill(0),
+ GPUBufferUsage.COPY_SRC
+ ),
+
+ size: testLocationsSize,
+ };
+
+ const readResultsSize = testingThreads * numReadOutputs * bytesPerWord;
+ const readResultsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: readResultsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.makeBufferWithContents(
+ new Uint32Array(readResultsSize).fill(0),
+ GPUBufferUsage.COPY_SRC
+ ),
+
+ size: readResultsSize,
+ };
+
+ const testResultsSize = this.params.numBehaviors * bytesPerWord;
+ const testResultsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: testResultsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ }),
+ srcBuf: this.test.makeBufferWithContents(
+ new Uint32Array(testResultsSize).fill(0),
+ GPUBufferUsage.COPY_SRC
+ ),
+
+ size: testResultsSize,
+ };
+
+ const shuffledWorkgroupsSize = this.params.maxWorkgroups * bytesPerWord;
+ const shuffledWorkgroupsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: shuffledWorkgroupsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.device.createBuffer({
+ size: shuffledWorkgroupsSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ }),
+ size: shuffledWorkgroupsSize,
+ };
+
+ const barrierSize = bytesPerWord;
+ const barrierBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: barrierSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.makeBufferWithContents(
+ new Uint32Array(barrierSize).fill(0),
+ GPUBufferUsage.COPY_SRC
+ ),
+
+ size: barrierSize,
+ };
+
+ const scratchpadSize = this.params.scratchMemorySize * bytesPerWord;
+ const scratchpadBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: scratchpadSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.makeBufferWithContents(
+ new Uint32Array(scratchpadSize).fill(0),
+ GPUBufferUsage.COPY_SRC
+ ),
+
+ size: scratchpadSize,
+ };
+
+ const scratchMemoryLocationsSize = this.params.maxWorkgroups * bytesPerWord;
+ const scratchMemoryLocationsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: scratchMemoryLocationsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
+ }),
+ srcBuf: this.test.device.createBuffer({
+ size: scratchMemoryLocationsSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ }),
+ size: scratchMemoryLocationsSize,
+ };
+
+ const stressParamsSize = numStressParams * bytesPerWord;
+ const stressParamsBuffer = {
+ deviceBuf: this.test.device.createBuffer({
+ size: stressParamsSize,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,
+ }),
+ srcBuf: this.test.device.createBuffer({
+ size: stressParamsSize,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ }),
+ size: stressParamsSize,
+ };
+
+ this.buffers = {
+ testLocations: testLocationsBuffer,
+ readResults: readResultsBuffer,
+ testResults: testResultsBuffer,
+ shuffledWorkgroups: shuffledWorkgroupsBuffer,
+ barrier: barrierBuffer,
+ scratchpad: scratchpadBuffer,
+ scratchMemoryLocations: scratchMemoryLocationsBuffer,
+ stressParams: stressParamsBuffer,
+ };
+
+ // set up pipeline layouts
+ const testLayout = this.test.device.createBindGroupLayout({
+ entries: [
+ { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 2, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'read-only-storage' } },
+ { binding: 3, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 4, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 5, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 6, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'uniform' } },
+ ],
+ });
+ this.testPipeline = this.test.device.createComputePipeline({
+ layout: this.test.device.createPipelineLayout({
+ bindGroupLayouts: [testLayout],
+ }),
+ compute: {
+ module: this.test.device.createShaderModule({
+ code: testShader,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ this.testBindGroup = this.test.device.createBindGroup({
+ entries: [
+ { binding: 0, resource: { buffer: this.buffers.testLocations.deviceBuf } },
+ { binding: 1, resource: { buffer: this.buffers.readResults.deviceBuf } },
+ { binding: 2, resource: { buffer: this.buffers.shuffledWorkgroups.deviceBuf } },
+ { binding: 3, resource: { buffer: this.buffers.barrier.deviceBuf } },
+ { binding: 4, resource: { buffer: this.buffers.scratchpad.deviceBuf } },
+ { binding: 5, resource: { buffer: this.buffers.scratchMemoryLocations.deviceBuf } },
+ { binding: 6, resource: { buffer: this.buffers.stressParams.deviceBuf } },
+ ],
+
+ layout: testLayout,
+ });
+
+ const resultLayout = this.test.device.createBindGroupLayout({
+ entries: [
+ { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 2, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
+ { binding: 3, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'uniform' } },
+ ],
+ });
+ this.resultPipeline = this.test.device.createComputePipeline({
+ layout: this.test.device.createPipelineLayout({
+ bindGroupLayouts: [resultLayout],
+ }),
+ compute: {
+ module: this.test.device.createShaderModule({
+ code: resultShader,
+ }),
+ entryPoint: 'main',
+ },
+ });
+ this.resultBindGroup = this.test.device.createBindGroup({
+ entries: [
+ { binding: 0, resource: { buffer: this.buffers.testLocations.deviceBuf } },
+ { binding: 1, resource: { buffer: this.buffers.readResults.deviceBuf } },
+ { binding: 2, resource: { buffer: this.buffers.testResults.deviceBuf } },
+ { binding: 3, resource: { buffer: this.buffers.stressParams.deviceBuf } },
+ ],
+
+ layout: resultLayout,
+ });
+ }
+
+ /**
+ * Run the test for the specified number of iterations. Checks the testResults buffer on the weakIndex; if
+ * this value is not 0 then the test has failed. The number of iterations is chosen per test so that the
+ * full set of tests meets some time budget while still being reasonably effective at uncovering issues.
+ * Currently, we aim for each test to complete in under one second.
+ */
+ async run(iterations, weakIndex) {
+ for (let i = 0; i < iterations; i++) {
+ const numWorkgroups = this.getRandomInRange(
+ this.params.testingWorkgroups,
+ this.params.maxWorkgroups
+ );
+
+ await this.setShuffledWorkgroups(numWorkgroups);
+ await this.setScratchLocations(numWorkgroups);
+ await this.setStressParams();
+ const encoder = this.test.device.createCommandEncoder();
+ this.copyBufferToBuffer(encoder, this.buffers.testLocations);
+ this.copyBufferToBuffer(encoder, this.buffers.readResults);
+ this.copyBufferToBuffer(encoder, this.buffers.testResults);
+ this.copyBufferToBuffer(encoder, this.buffers.barrier);
+ this.copyBufferToBuffer(encoder, this.buffers.shuffledWorkgroups);
+ this.copyBufferToBuffer(encoder, this.buffers.scratchpad);
+ this.copyBufferToBuffer(encoder, this.buffers.scratchMemoryLocations);
+ this.copyBufferToBuffer(encoder, this.buffers.stressParams);
+
+ const testPass = encoder.beginComputePass();
+ testPass.setPipeline(this.testPipeline);
+ testPass.setBindGroup(0, this.testBindGroup);
+ testPass.dispatchWorkgroups(numWorkgroups);
+ testPass.end();
+
+ const resultPass = encoder.beginComputePass();
+ resultPass.setPipeline(this.resultPipeline);
+ resultPass.setBindGroup(0, this.resultBindGroup);
+ resultPass.dispatchWorkgroups(this.params.testingWorkgroups);
+ resultPass.end();
+
+ this.test.device.queue.submit([encoder.finish()]);
+ this.test.expectGPUBufferValuesPassCheck(
+ this.buffers.testResults.deviceBuf,
+ this.checkWeakIndex(weakIndex),
+ {
+ type: Uint32Array,
+ typedLength: this.params.numBehaviors,
+ }
+ );
+ }
+ }
+
+ /** Returns a function that checks whether the test passes, given a weak index and the test results buffer. */
+ checkWeakIndex(weakIndex) {
+ const checkResult = this.checkResult(weakIndex);
+ const resultPrinter = this.resultPrinter(weakIndex);
+ return function (a) {
+ return checkElementsPassPredicate(a, checkResult, {
+ predicatePrinter: [{ leftHeader: 'expected ==', getValueForCell: resultPrinter }],
+ });
+ };
+ }
+
+ /**
+ * Returns a function that checks whether the specified weak index's value is not equal to 0.
+ * If the weak index's value is not 0, it means the test has observed a behavior disallowed by the memory model and
+ * is considered a test failure.
+ */
+ checkResult(weakIndex) {
+ return function (i, v) {
+ if (i === weakIndex && v > 0) {
+ return false;
+ }
+ return true;
+ };
+ }
+
+ /** Returns a printer function that visualizes the results of checking the test results. */
+ resultPrinter(weakIndex) {
+ return function (i) {
+ if (i === weakIndex) {
+ return 0;
+ } else {
+ return 'any value';
+ }
+ };
+ }
+
+ /** Utility method that simplifies copying source buffers to device buffers. */
+ copyBufferToBuffer(encoder, buffer) {
+ encoder.copyBufferToBuffer(buffer.srcBuf, 0, buffer.deviceBuf, 0, buffer.size);
+ }
+
+ /** Returns a random integer between 0 and the max. */
+ getRandomInt(max) {
+ return Math.floor(Math.random() * max);
+ }
+
+ /** Returns a random number in between the min and max values. */
+ getRandomInRange(min, max) {
+ if (min === max) {
+ return min;
+ } else {
+ const offset = this.getRandomInt(max - min);
+ return min + offset;
+ }
+ }
+
+ /** Returns a permuted array using a simple Fisher-Yates shuffle algorithm. */
+ shuffleArray(a) {
+ for (let i = a.length - 1; i >= 0; i--) {
+ const toSwap = this.getRandomInt(i + 1);
+ const temp = a[toSwap];
+ a[toSwap] = a[i];
+ a[i] = temp;
+ }
+ }
+
+ /**
+ * Shuffles the order of workgroup ids, so that threads operating on the same memory location are not always in
+ * consecutive workgroups.
+ */
+ async setShuffledWorkgroups(numWorkgroups) {
+ await this.buffers.shuffledWorkgroups.srcBuf.mapAsync(GPUMapMode.WRITE);
+ const shuffledWorkgroupsBuffer = this.buffers.shuffledWorkgroups.srcBuf.getMappedRange();
+ const shuffledWorkgroupsArray = new Uint32Array(shuffledWorkgroupsBuffer);
+ for (let i = 0; i < numWorkgroups; i++) {
+ shuffledWorkgroupsArray[i] = i;
+ }
+ if (this.getRandomInt(100) < this.params.shufflePct) {
+ for (let i = numWorkgroups - 1; i > 0; i--) {
+ const x = this.getRandomInt(i + 1);
+ const temp = shuffledWorkgroupsArray[i];
+ shuffledWorkgroupsArray[i] = shuffledWorkgroupsArray[x];
+ shuffledWorkgroupsArray[x] = temp;
+ }
+ }
+ this.buffers.shuffledWorkgroups.srcBuf.unmap();
+ }
+
+ /** Sets the memory locations that stressing workgroups will access. Uses either a chunking or round robin assignment strategy. */
+ async setScratchLocations(numWorkgroups) {
+ await this.buffers.scratchMemoryLocations.srcBuf.mapAsync(GPUMapMode.WRITE);
+ const scratchLocationsArrayBuffer = this.buffers.scratchMemoryLocations.srcBuf.getMappedRange();
+ const scratchLocationsArray = new Uint32Array(scratchLocationsArrayBuffer);
+ const scratchNumRegions = this.params.scratchMemorySize / this.params.stressLineSize;
+ const scratchRegions = [...Array(scratchNumRegions).keys()];
+ this.shuffleArray(scratchRegions);
+ for (let i = 0; i < this.params.stressTargetLines; i++) {
+ const region = scratchRegions[i];
+ const locInRegion = this.getRandomInt(this.params.stressLineSize);
+ if (this.getRandomInt(100) < this.params.stressStrategyBalancePct) {
+ // In the round-robin case, the current scratch location is striped across all workgroups.
+ for (let j = i; j < numWorkgroups; j += this.params.stressTargetLines) {
+ scratchLocationsArray[j] = region * this.params.stressLineSize + locInRegion;
+ }
+ } else {
+ // In the chunking case, the current scratch location is assigned to a block of workgroups. The final scratch
+ // location may be assigned to more workgroups, if the number of scratch locations does not cleanly divide the
+ // number of workgroups.
+ const workgroupsPerLocation = numWorkgroups / this.params.stressTargetLines;
+ for (let j = 0; j < workgroupsPerLocation; j++) {
+ scratchLocationsArray[i * workgroupsPerLocation + j] =
+ region * this.params.stressLineSize + locInRegion;
+ }
+ if (
+ i === this.params.stressTargetLines - 1 &&
+ numWorkgroups % this.params.stressTargetLines !== 0
+ ) {
+ for (let j = 0; j < numWorkgroups % this.params.stressTargetLines; j++) {
+ scratchLocationsArray[numWorkgroups - j - 1] =
+ region * this.params.stressLineSize + locInRegion;
+ }
+ }
+ }
+ }
+ this.buffers.scratchMemoryLocations.srcBuf.unmap();
+ }
+
+ /** Sets the parameters that are used by the shader to calculate memory locations and perform stress. */
+ async setStressParams() {
+ await this.buffers.stressParams.srcBuf.mapAsync(GPUMapMode.WRITE);
+ const stressParamsArrayBuffer = this.buffers.stressParams.srcBuf.getMappedRange();
+ const stressParamsArray = new Uint32Array(stressParamsArrayBuffer);
+ if (this.getRandomInt(100) < this.params.barrierPct) {
+ stressParamsArray[barrierParamIndex] = 1;
+ } else {
+ stressParamsArray[barrierParamIndex] = 0;
+ }
+ if (this.getRandomInt(100) < this.params.memStressPct) {
+ stressParamsArray[memStressIndex] = 1;
+ } else {
+ stressParamsArray[memStressIndex] = 0;
+ }
+ stressParamsArray[memStressIterationsIndex] = this.params.memStressIterations;
+ const memStressStoreFirst = this.getRandomInt(100) < this.params.memStressStoreFirstPct;
+ const memStressStoreSecond = this.getRandomInt(100) < this.params.memStressStoreSecondPct;
+ let memStressPattern;
+ if (memStressStoreFirst && memStressStoreSecond) {
+ memStressPattern = 0;
+ } else if (memStressStoreFirst && !memStressStoreSecond) {
+ memStressPattern = 1;
+ } else if (!memStressStoreFirst && memStressStoreSecond) {
+ memStressPattern = 2;
+ } else {
+ memStressPattern = 3;
+ }
+ stressParamsArray[memStressPatternIndex] = memStressPattern;
+ if (this.getRandomInt(100) < this.params.preStressPct) {
+ stressParamsArray[preStressIndex] = 1;
+ } else {
+ stressParamsArray[preStressIndex] = 0;
+ }
+ stressParamsArray[preStressIterationsIndex] = this.params.preStressIterations;
+ const preStressStoreFirst = this.getRandomInt(100) < this.params.preStressStoreFirstPct;
+ const preStressStoreSecond = this.getRandomInt(100) < this.params.preStressStoreSecondPct;
+ let preStressPattern;
+ if (preStressStoreFirst && preStressStoreSecond) {
+ preStressPattern = 0;
+ } else if (preStressStoreFirst && !preStressStoreSecond) {
+ preStressPattern = 1;
+ } else if (!preStressStoreFirst && preStressStoreSecond) {
+ preStressPattern = 2;
+ } else {
+ preStressPattern = 3;
+ }
+ stressParamsArray[preStressPatternIndex] = preStressPattern;
+ stressParamsArray[permuteFirstIndex] = this.params.permuteFirst;
+ stressParamsArray[permuteSecondIndex] = this.params.permuteSecond;
+ stressParamsArray[testingWorkgroupsIndex] = this.params.testingWorkgroups;
+ stressParamsArray[memStrideIndex] = this.params.memStride;
+ if (this.params.aliasedMemory) {
+ stressParamsArray[memLocationOffsetIndex] = 0;
+ } else {
+ stressParamsArray[memLocationOffsetIndex] = this.params.memStride;
+ }
+ this.buffers.stressParams.srcBuf.unmap();
+ }
+}
+
+/** Defines common data structures used in memory model test shaders. */
+const shaderMemStructures = `
+ struct Memory {
+ value: array<u32>
+ };
+
+ struct AtomicMemory {
+ value: array<atomic<u32>>
+ };
+
+ struct ReadResult {
+ r0: atomic<u32>,
+ r1: atomic<u32>,
+ };
+
+ struct ReadResults {
+ value: array<ReadResult>
+ };
+
+ struct StressParamsMemory {
+ do_barrier: u32,
+ mem_stress: u32,
+ mem_stress_iterations: u32,
+ mem_stress_pattern: u32,
+ pre_stress: u32,
+ pre_stress_iterations: u32,
+ pre_stress_pattern: u32,
+ permute_first: u32,
+ permute_second: u32,
+ testing_workgroups: u32,
+ mem_stride: u32,
+ location_offset: u32,
+ };
+`;
+
+/**
+ * Structure to hold the counts of occurrences of the possible behaviors of a two-thread, four-instruction test.
+ * "seq0" means the first invocation's instructions are observed to have occurred before the second invocation's instructions.
+ * "seq1" means the second invocation's instructions are observed to have occurred before the first invocation's instructions.
+ * "interleaved" means there was an observation of some interleaving of instructions between the two invocations.
+ * "weak" means there was an observation of some ordering of instructions that is inconsistent with the WebGPU memory model.
+ */
+const fourBehaviorTestResultStructure = `
+ struct TestResults {
+ seq0: atomic<u32>,
+ seq1: atomic<u32>,
+ interleaved: atomic<u32>,
+ weak: atomic<u32>,
+ };
+`;
+
+/**
+ * Defines the possible behaviors of a two instruction test. Used to test the behavior of non-atomic memory with barriers and
+ * one-thread coherence tests.
+ * "seq" means that the expected, sequential behavior occurred.
+ * "weak" means that an unexpected, inconsistent behavior occurred.
+ */
+const twoBehaviorTestResultStructure = `
+ struct TestResults {
+ seq: atomic<u32>,
+ weak: atomic<u32>,
+ };
+`;
+
+/** Common bindings used in the test shader phase of a test. */
+const commonTestShaderBindings = `
+ @group(0) @binding(1) var<storage, read_write> results : ReadResults;
+ @group(0) @binding(2) var<storage, read> shuffled_workgroups : Memory;
+ @group(0) @binding(3) var<storage, read_write> barrier : AtomicMemory;
+ @group(0) @binding(4) var<storage, read_write> scratchpad : Memory;
+ @group(0) @binding(5) var<storage, read_write> scratch_locations : Memory;
+ @group(0) @binding(6) var<uniform> stress_params : StressParamsMemory;
+`;
+
+/** The combined bindings for a test on atomic memory. */
+const atomicTestShaderBindings = [
+ `
+ @group(0) @binding(0) var<storage, read_write> test_locations : AtomicMemory;
+`,
+ commonTestShaderBindings,
+].join('\n');
+
+/** The combined bindings for a test on non-atomic memory. */
+const nonAtomicTestShaderBindings = [
+ `
+ @group(0) @binding(0) var<storage, read_write> test_locations : Memory;
+`,
+ commonTestShaderBindings,
+].join('\n');
+
+/** Bindings used in the result aggregation phase of the test. */
+const resultShaderBindings = `
+ @group(0) @binding(0) var<storage, read_write> test_locations : AtomicMemory;
+ @group(0) @binding(1) var<storage, read_write> read_results : ReadResults;
+ @group(0) @binding(2) var<storage, read_write> test_results : TestResults;
+ @group(0) @binding(3) var<uniform> stress_params : StressParamsMemory;
+`;
+
+/**
+ * For tests that operate on workgroup memory, include this definition. 3584 memory locations is
+ * large enough to accommodate the maximum memory size needed per workgroup for testing, which is
+ * 256 invocations per workgroup x 2 memory locations x 7 (memStride, or max stride between successive memory locations).
+ * Should change to a pipeline overridable constant when possible.
+ */
+const atomicWorkgroupMemory = `
+ var<workgroup> wg_test_locations: array<atomic<u32>, 3584>;
+`;
+
+/**
+ * For tests that operate on non-atomic workgroup memory, include this definition. 3584 memory locations
+ * is large enough to accommodate the maximum memory size needed per workgroup for testing.
+ */
+const nonAtomicWorkgroupMemory = `
+ var<workgroup> wg_test_locations: array<u32, 3584>;
+`;
+
+/**
+ * Functions used to calculate memory locations for each invocation, for both testing and result aggregation.
+ * The permute function ensures a random permutation based on multiplying and modding by coprime numbers. The stripe
+ * workgroup function ensures that invocations coordinating on a test are spread out across different workgroups.
+ */
+const memoryLocationFunctions = `
+ fn permute_id(id: u32, factor: u32, mask: u32) -> u32 {
+ return (id * factor) % mask;
+ }
+
+ fn stripe_workgroup(workgroup_id: u32, local_id: u32) -> u32 {
+ return (workgroup_id + 1u + local_id % (stress_params.testing_workgroups - 1u)) % stress_params.testing_workgroups;
+ }
+`;
+
+/** Functions that help add stress to the test. */
+const testShaderFunctions = `
+ //Force the invocations in the workgroup to wait for each other, but without the general memory ordering
+ // effects of a control barrier. The barrier spins until either all invocations have incremented the atomic
+ // variable or 1024 loops have occurred. 1024 was chosen because it gives more time for invocations to enter
+ // the barrier but does not overly reduce testing throughput.
+ fn spin(limit: u32) {
+ var i : u32 = 0u;
+ var bar_val : u32 = atomicAdd(&barrier.value[0], 1u);
+ loop {
+ if (i == 1024u || bar_val >= limit) {
+ break;
+ }
+ bar_val = atomicAdd(&barrier.value[0], 0u);
+ i = i + 1u;
+ }
+ }
+
+ // Perform iterations of stress, depending on the specified pattern. Pattern 0 is store-store, pattern 1 is store-load,
+ // pattern 2 is load-store, and pattern 3 is load-load. The extra if condition (if tmpX > 100000u), is used to avoid
+ // the compiler optimizing out unused loads, where 100,000 is larger than the maximum number of stress iterations used
+ // in any test.
+ fn do_stress(iterations: u32, pattern: u32, workgroup_id: u32) {
+ let addr = scratch_locations.value[workgroup_id];
+ switch(pattern) {
+ case 0u: {
+ for(var i: u32 = 0u; i < iterations; i = i + 1u) {
+ scratchpad.value[addr] = i;
+ scratchpad.value[addr] = i + 1u;
+ }
+ }
+ case 1u: {
+ for(var i: u32 = 0u; i < iterations; i = i + 1u) {
+ scratchpad.value[addr] = i;
+ let tmp1: u32 = scratchpad.value[addr];
+ if (tmp1 > 100000u) {
+ scratchpad.value[addr] = i;
+ break;
+ }
+ }
+ }
+ case 2u: {
+ for(var i: u32 = 0u; i < iterations; i = i + 1u) {
+ let tmp1: u32 = scratchpad.value[addr];
+ if (tmp1 > 100000u) {
+ scratchpad.value[addr] = i;
+ break;
+ }
+ scratchpad.value[addr] = i;
+ }
+ }
+ case 3u: {
+ for(var i: u32 = 0u; i < iterations; i = i + 1u) {
+ let tmp1: u32 = scratchpad.value[addr];
+ if (tmp1 > 100000u) {
+ scratchpad.value[addr] = i;
+ break;
+ }
+ let tmp2: u32 = scratchpad.value[addr];
+ if (tmp2 > 100000u) {
+ scratchpad.value[addr] = i;
+ break;
+ }
+ }
+ }
+ default: {
+ }
+ }
+ }
+`;
+
+/**
+ * Entry point to both test and result shaders. One-dimensional workgroup size is hardcoded to 256, until
+ * pipeline overridable constants are supported.
+ */
+const shaderEntryPoint = `
+ // Change to pipeline overridable constant when possible.
+ const workgroupXSize = 256u;
+ @compute @workgroup_size(workgroupXSize) fn main(
+ @builtin(local_invocation_id) local_invocation_id : vec3<u32>,
+ @builtin(workgroup_id) workgroup_id : vec3<u32>) {
+`;
+
+/** All test shaders first calculate the shuffled workgroup. */
+const testShaderCommonHeader = `
+ let shuffled_workgroup = shuffled_workgroups.value[workgroup_id[0]];
+ if (shuffled_workgroup < stress_params.testing_workgroups) {
+`;
+
+/**
+ * All test shaders must calculate addresses for memory locations used in the test. Not all these addresses are
+ * used in every test, but no test uses more than these addresses.
+ */
+const testShaderCommonCalculations = `
+ let x_0 = id_0 * stress_params.mem_stride * 2u;
+ let y_0 = permute_id(id_0, stress_params.permute_second, total_ids) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ let x_1 = id_1 * stress_params.mem_stride * 2u;
+ let y_1 = permute_id(id_1, stress_params.permute_second, total_ids) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ if (stress_params.pre_stress == 1u) {
+ do_stress(stress_params.pre_stress_iterations, stress_params.pre_stress_pattern, shuffled_workgroup);
+ }
+`;
+
+/**
+ * An inter-workgroup test calculates two sets of memory locations that are guaranteed to be in separate workgroups.
+ * If the bounded spin-loop barrier is called, it attempts to wait for all invocations in all workgroups.
+ */
+const interWorkgroupTestShaderCode = [
+ `
+ let total_ids = workgroupXSize * stress_params.testing_workgroups;
+ let id_0 = shuffled_workgroup * workgroupXSize + local_invocation_id[0];
+ let new_workgroup = stripe_workgroup(shuffled_workgroup, local_invocation_id[0]);
+ let id_1 = new_workgroup * workgroupXSize + permute_id(local_invocation_id[0], stress_params.permute_first, workgroupXSize);
+`,
+ testShaderCommonCalculations,
+ `
+ if (stress_params.do_barrier == 1u) {
+ spin(workgroupXSize * stress_params.testing_workgroups);
+ }
+`,
+].join('\n');
+
+/**
+ * An intra-workgroup test calculates two set of memory locations that are guaranteed to be in the same workgroup.
+ * If the bounded spin-loop barrier is called, it attempts to wait for all invocations in the same workgroup.
+ */
+const intraWorkgroupTestShaderCode = [
+ `
+ let total_ids = workgroupXSize;
+ let id_0 = local_invocation_id[0];
+ let id_1 = permute_id(local_invocation_id[0], stress_params.permute_first, workgroupXSize);
+`,
+ testShaderCommonCalculations,
+ `
+ if (stress_params.do_barrier == 1u) {
+ spin(workgroupXSize);
+ }
+`,
+].join('\n');
+
+/**
+ * Tests that operate on storage memory and communicate with invocations in the same workgroup must offset their locations
+ * relative to global memory.
+ */
+const storageIntraWorkgroupTestShaderCode = `
+ let total_ids = workgroupXSize;
+ let id_0 = local_invocation_id[0];
+ let id_1 = permute_id(local_invocation_id[0], stress_params.permute_first, workgroupXSize);
+ let x_0 = (shuffled_workgroup * workgroupXSize + id_0) * stress_params.mem_stride * 2u;
+ let y_0 = (shuffled_workgroup * workgroupXSize + permute_id(id_0, stress_params.permute_second, total_ids)) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ let x_1 = (shuffled_workgroup * workgroupXSize + id_1) * stress_params.mem_stride * 2u;
+ let y_1 = (shuffled_workgroup * workgroupXSize + permute_id(id_1, stress_params.permute_second, total_ids)) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ if (stress_params.pre_stress == 1u) {
+ do_stress(stress_params.pre_stress_iterations, stress_params.pre_stress_pattern, shuffled_workgroup);
+ }
+ if (stress_params.do_barrier == 1u) {
+ spin(workgroupXSize);
+ }
+`;
+
+/** All test shaders may perform stress with non-testing threads. */
+const testShaderCommonFooter = `
+ } else if (stress_params.mem_stress == 1u) {
+ do_stress(stress_params.mem_stress_iterations, stress_params.mem_stress_pattern, shuffled_workgroup);
+ }
+ }
+`;
+
+/**
+ * All result shaders must calculate memory locations used in the test. Not all these locations are
+ * used in every result shader, but no result shader uses more than these locations.
+ */
+const resultShaderCommonCalculations = `
+ let id_0 = workgroup_id[0] * workgroupXSize + local_invocation_id[0];
+ let x_0 = id_0 * stress_params.mem_stride * 2u;
+ let mem_x_0 = atomicLoad(&test_locations.value[x_0]);
+ let r0 = atomicLoad(&read_results.value[id_0].r0);
+ let r1 = atomicLoad(&read_results.value[id_0].r1);
+`;
+
+/** Common result shader code for an inter-workgroup test. */
+const interWorkgroupResultShaderCode = [
+ resultShaderCommonCalculations,
+ `
+ let total_ids = workgroupXSize * stress_params.testing_workgroups;
+ let y_0 = permute_id(id_0, stress_params.permute_second, total_ids) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ let mem_y_0 = atomicLoad(&test_locations.value[y_0]);
+`,
+].join('\n');
+
+/** Common result shader code for an intra-workgroup test. */
+const intraWorkgroupResultShaderCode = [
+ resultShaderCommonCalculations,
+ `
+ let total_ids = workgroupXSize;
+ let y_0 = (workgroup_id[0] * workgroupXSize + permute_id(local_invocation_id[0], stress_params.permute_second, total_ids)) * stress_params.mem_stride * 2u + stress_params.location_offset;
+ let mem_y_0 = atomicLoad(&test_locations.value[y_0]);
+`,
+].join('\n');
+
+/** Ending bracket for result shaders. */
+const resultShaderCommonFooter = `
+}
+`;
+
+/** The common shader code for test shaders that perform atomic storage class memory litmus tests. */
+const storageMemoryAtomicTestShaderCode = [
+ shaderMemStructures,
+ atomicTestShaderBindings,
+ memoryLocationFunctions,
+ testShaderFunctions,
+ shaderEntryPoint,
+ testShaderCommonHeader,
+].join('\n');
+
+/** The common shader code for test shaders that perform non-atomic storage class memory litmus tests. */
+const storageMemoryNonAtomicTestShaderCode = [
+ shaderMemStructures,
+ nonAtomicTestShaderBindings,
+ memoryLocationFunctions,
+ testShaderFunctions,
+ shaderEntryPoint,
+ testShaderCommonHeader,
+].join('\n');
+
+/** The common shader code for test shaders that perform atomic workgroup class memory litmus tests. */
+const workgroupMemoryAtomicTestShaderCode = [
+ shaderMemStructures,
+ atomicTestShaderBindings,
+ atomicWorkgroupMemory,
+ memoryLocationFunctions,
+ testShaderFunctions,
+ shaderEntryPoint,
+ testShaderCommonHeader,
+].join('\n');
+
+/** The common shader code for test shaders that perform non-atomic workgroup class memory litmus tests. */
+const workgroupMemoryNonAtomicTestShaderCode = [
+ shaderMemStructures,
+ nonAtomicTestShaderBindings,
+ nonAtomicWorkgroupMemory,
+ memoryLocationFunctions,
+ testShaderFunctions,
+ shaderEntryPoint,
+ testShaderCommonHeader,
+].join('\n');
+
+/** The common shader code for all result shaders. */
+const resultShaderCommonCode = [
+ shaderMemStructures,
+ resultShaderBindings,
+ memoryLocationFunctions,
+ shaderEntryPoint,
+].join('\n');
+
+/**
+ * Defines the types of possible memory a test is operating on. Used as part of the process of building shader code from
+ * its composite parts.
+ */
+export let MemoryType;
+
+/**
+ * Defines the relative positions of two invocations coordinating on a test. Used as part of the process of building shader
+ * code from its composite parts.
+ */ (function (MemoryType) {
+ MemoryType['AtomicStorageClass'] = 'atomic_storage';
+ MemoryType['NonAtomicStorageClass'] = 'non_atomic_storage';
+ MemoryType['AtomicWorkgroupClass'] = 'atomic_workgroup';
+ MemoryType['NonAtomicWorkgroupClass'] = 'non_atomic_workgroup';
+})(MemoryType || (MemoryType = {}));
+export let TestType;
+
+/** Defines the number of behaviors a test may have. */ (function (TestType) {
+ TestType['InterWorkgroup'] = 'inter_workgroup';
+ TestType['IntraWorkgroup'] = 'intra_workgroup';
+})(TestType || (TestType = {}));
+export let ResultType;
+
+/**
+ * Given test code that performs the actual sequence of loads and stores, as well as a memory type and test type, returns
+ * a complete test shader.
+ */ (function (ResultType) {
+ ResultType[(ResultType['TwoBehavior'] = 0)] = 'TwoBehavior';
+ ResultType[(ResultType['FourBehavior'] = 1)] = 'FourBehavior';
+})(ResultType || (ResultType = {}));
+export function buildTestShader(testCode, memoryType, testType) {
+ let memoryTypeCode;
+ let isStorageAS = false;
+ switch (memoryType) {
+ case MemoryType.AtomicStorageClass:
+ memoryTypeCode = storageMemoryAtomicTestShaderCode;
+ isStorageAS = true;
+ break;
+ case MemoryType.NonAtomicStorageClass:
+ memoryTypeCode = storageMemoryNonAtomicTestShaderCode;
+ isStorageAS = true;
+ break;
+ case MemoryType.AtomicWorkgroupClass:
+ memoryTypeCode = workgroupMemoryAtomicTestShaderCode;
+ break;
+ case MemoryType.NonAtomicWorkgroupClass:
+ memoryTypeCode = workgroupMemoryNonAtomicTestShaderCode;
+ }
+
+ let testTypeCode;
+ switch (testType) {
+ case TestType.InterWorkgroup:
+ testTypeCode = interWorkgroupTestShaderCode;
+ break;
+ case TestType.IntraWorkgroup:
+ if (isStorageAS) {
+ testTypeCode = storageIntraWorkgroupTestShaderCode;
+ } else {
+ testTypeCode = intraWorkgroupTestShaderCode;
+ }
+ }
+
+ return [memoryTypeCode, testTypeCode, testCode, testShaderCommonFooter].join('\n');
+}
+
+/**
+ * Given result code that aggregates the possible behaviors of a test across all instances, as well as a test type and
+ * number of behaviors, returns a complete result shader.
+ */
+export function buildResultShader(resultCode, testType, resultType) {
+ let resultStructure;
+ switch (resultType) {
+ case ResultType.TwoBehavior:
+ resultStructure = twoBehaviorTestResultStructure;
+ break;
+ case ResultType.FourBehavior:
+ resultStructure = fourBehaviorTestResultStructure;
+ }
+
+ let testTypeCode;
+ switch (testType) {
+ case TestType.InterWorkgroup:
+ testTypeCode = interWorkgroupResultShaderCode;
+ break;
+ case TestType.IntraWorkgroup:
+ testTypeCode = intraWorkgroupResultShaderCode;
+ }
+
+ return [
+ resultStructure,
+ resultShaderCommonCode,
+ testTypeCode,
+ resultCode,
+ resultShaderCommonFooter,
+ ].join('\n');
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/weak.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/weak.spec.js
new file mode 100644
index 0000000000..a9f7e60ce1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/memory_model/weak.spec.js
@@ -0,0 +1,447 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for properties of the WebGPU memory model involving two memory locations.
+Specifically, the acquire/release ordering provided by WebGPU's barriers can be used to disallow
+weak behaviors in several classic memory model litmus tests.`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+import {
+ MemoryModelTester,
+ buildTestShader,
+ MemoryType,
+ TestType,
+ buildResultShader,
+ ResultType,
+} from './memory_model_setup.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// A reasonable parameter set, determined heuristically.
+const memoryModelTestParams = {
+ workgroupSize: 256,
+ testingWorkgroups: 739,
+ maxWorkgroups: 885,
+ shufflePct: 0,
+ barrierPct: 0,
+ memStressPct: 0,
+ memStressIterations: 1024,
+ memStressStoreFirstPct: 50,
+ memStressStoreSecondPct: 50,
+ preStressPct: 100,
+ preStressIterations: 33,
+ preStressStoreFirstPct: 0,
+ preStressStoreSecondPct: 100,
+ scratchMemorySize: 1408,
+ stressLineSize: 4,
+ stressTargetLines: 11,
+ stressStrategyBalancePct: 0,
+ permuteFirst: 109,
+ permuteSecond: 419,
+ memStride: 2,
+ aliasedMemory: false,
+ numBehaviors: 4,
+};
+
+const workgroupMemoryMessagePassingTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[y_0], 1u);
+ let r0 = atomicLoad(&wg_test_locations[y_1]);
+ workgroupBarrier();
+ let r1 = atomicLoad(&wg_test_locations[x_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const storageMemoryMessagePassingTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ storageBarrier();
+ atomicStore(&test_locations.value[y_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[y_1]);
+ storageBarrier();
+ let r1 = atomicLoad(&test_locations.value[x_1]);
+ atomicStore(&results.value[shuffled_workgroup * u32(workgroupXSize) + id_1].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * u32(workgroupXSize) + id_1].r1, r1);
+`;
+
+g.test('message_passing')
+ .desc(
+ `Checks whether two reads on one thread can observe two writes in another thread in a way
+ that is inconsistent with sequential consistency. In the message passing litmus test, one
+ thread writes the value 1 to some location x and then 1 to some location y. The second thread
+ reads y and then x. If the second thread reads y == 1 and x == 0, then sequential consistency
+ has not been respected. The acquire/release semantics of WebGPU's barrier functions should disallow
+ this behavior within a workgroup.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemoryMessagePassingTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemoryMessagePassingTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((r0 == 0u && r1 == 0u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 1u && r1 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && r1 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 1u && r1 == 0u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
+
+const workgroupMemoryStoreTestCode = `
+ atomicStore(&wg_test_locations[x_0], 2u);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[y_0], 1u);
+ let r0 = atomicLoad(&wg_test_locations[y_1]);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[x_1], 1u);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+`;
+
+const storageMemoryStoreTestCode = `
+ atomicStore(&test_locations.value[x_0], 2u);
+ storageBarrier();
+ atomicStore(&test_locations.value[y_0], 1u);
+ let r0 = atomicLoad(&test_locations.value[y_1]);
+ storageBarrier();
+ atomicStore(&test_locations.value[x_1], 1u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+`;
+
+g.test('store')
+ .desc(
+ `In the store litmus test, one thread writes 2 to some memory location x and then 1 to some memory location
+ y. A second thread reads the value of y and then writes 1 to x. If the read on the second thread returns 1,
+ but the value of x in memory after the test ends is 2, then there has been a re-ordering which is not allowed
+ when using WebGPU's barriers.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemoryStoreTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemoryStoreTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((r0 == 1u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 0u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && mem_x_0 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 1u && mem_x_0 == 2u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
+
+const workgroupMemoryLoadBufferTestCode = `
+ let r0 = atomicLoad(&wg_test_locations[y_0]);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[x_0], 1u);
+ let r1 = atomicLoad(&wg_test_locations[x_1]);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[y_1], 1u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const storageMemoryLoadBufferTestCode = `
+ let r0 = atomicLoad(&test_locations.value[y_0]);
+ storageBarrier();
+ atomicStore(&test_locations.value[x_0], 1u);
+ let r1 = atomicLoad(&test_locations.value[x_1]);
+ storageBarrier();
+ atomicStore(&test_locations.value[y_1], 1u);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+g.test('load_buffer')
+ .desc(
+ `In the load buffer litmus test, one thread reads from memory location y and then writes 1 to memory location x.
+ A second thread reads from x and then writes 1 to y. If both threads read the value 0, then the loads have been
+ buffered or re-ordered, which is not allowed when used in conjunction with WebGPU's barriers.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemoryLoadBufferTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemoryLoadBufferTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((r0 == 1u && r1 == 0u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 0u && r1 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 0u && r1 == 0u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 1u && r1 == 1u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
+
+const workgroupMemoryReadTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ workgroupBarrier();
+ atomicExchange(&wg_test_locations[y_0], 1u);
+ atomicExchange(&wg_test_locations[y_1], 2u);
+ workgroupBarrier();
+ let r0 = atomicLoad(&wg_test_locations[x_1]);
+ workgroupBarrier();
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + y_1], atomicLoad(&wg_test_locations[y_1]));
+`;
+
+const storageMemoryReadTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ storageBarrier();
+ atomicExchange(&test_locations.value[y_0], 1u);
+ atomicExchange(&test_locations.value[y_1], 2u);
+ storageBarrier();
+ let r0 = atomicLoad(&test_locations.value[x_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r0, r0);
+`;
+
+g.test('read')
+ .desc(
+ `In the read litmus test, one thread writes 1 to memory location x and then 1 to memory location y. A second thread
+ first writes 2 to y and then reads from x. If the value read by the second thread is 0 but the value in memory of y
+ after the test completes is 2, then there has been some re-ordering of instructions disallowed when using WebGPU's
+ barrier. Additionally, both writes to y are RMWs, so that the barrier forces the correct acquire/release memory ordering
+ synchronization.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemoryReadTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemoryReadTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((r0 == 1u && mem_y_0 == 2u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 0u && mem_y_0 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 1u && mem_y_0 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 0u && mem_y_0 == 2u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
+
+const workgroupMemoryStoreBufferTestCode = `
+ atomicStore(&wg_test_locations[x_0], 1u);
+ workgroupBarrier();
+ let r0 = atomicAdd(&wg_test_locations[y_0], 0u);
+ atomicExchange(&wg_test_locations[y_1], 1u);
+ workgroupBarrier();
+ let r1 = atomicLoad(&wg_test_locations[x_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+const storageMemoryStoreBufferTestCode = `
+ atomicStore(&test_locations.value[x_0], 1u);
+ storageBarrier();
+ let r0 = atomicAdd(&test_locations.value[y_0], 0u);
+ atomicExchange(&test_locations.value[y_1], 1u);
+ storageBarrier();
+ let r1 = atomicLoad(&test_locations.value[x_1]);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0);
+ atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_1].r1, r1);
+`;
+
+g.test('store_buffer')
+ .desc(
+ `In the store buffer litmus test, one thread writes 1 to memory location x and then reads from memory location
+ y. A second thread writes 1 to y and then reads from x. If both reads return 0, then stores have been buffered
+ or some other re-ordering has occurred that is disallowed by WebGPU's barriers. Additionally, both the read
+ and store to y are RMWs to achieve the necessary synchronization across threads.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemoryStoreBufferTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemoryStoreBufferTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((r0 == 1u && r1 == 0u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((r0 == 0u && r1 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((r0 == 1u && r1 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((r0 == 0u && r1 == 0u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
+
+const workgroupMemory2P2WTestCode = `
+ atomicStore(&wg_test_locations[x_0], 2u);
+ workgroupBarrier();
+ atomicExchange(&wg_test_locations[y_0], 1u);
+ atomicExchange(&wg_test_locations[y_1], 2u);
+ workgroupBarrier();
+ atomicStore(&wg_test_locations[x_1], 1u);
+ workgroupBarrier();
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1]));
+ atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + y_1], atomicLoad(&wg_test_locations[y_1]));
+`;
+
+const storageMemory2P2WTestCode = `
+ atomicStore(&test_locations.value[x_0], 2u);
+ storageBarrier();
+ atomicExchange(&test_locations.value[y_0], 1u);
+ atomicExchange(&test_locations.value[y_1], 2u);
+ storageBarrier();
+ atomicStore(&test_locations.value[x_1], 1u);
+`;
+
+g.test('2_plus_2_write')
+ .desc(
+ `In the 2+2 write litmus test, one thread stores 2 to memory location x and then 1 to memory location y.
+ A second thread stores 2 to y and then 1 to x. If at the end of the test both memory locations are set to 2,
+ then some disallowed re-ordering has occurred. Both writes to y are RMWs to achieve the required synchronization.
+ `
+ )
+ .paramsSimple([
+ { memType: MemoryType.AtomicWorkgroupClass, _testCode: workgroupMemory2P2WTestCode },
+ { memType: MemoryType.AtomicStorageClass, _testCode: storageMemory2P2WTestCode },
+ ])
+ .fn(async t => {
+ const testShader = buildTestShader(
+ t.params._testCode,
+ t.params.memType,
+ TestType.IntraWorkgroup
+ );
+
+ const messagePassingResultShader = buildResultShader(
+ `
+ if ((mem_x_0 == 1u && mem_y_0 == 2u)) {
+ atomicAdd(&test_results.seq0, 1u);
+ } else if ((mem_x_0 == 2u && mem_y_0 == 1u)) {
+ atomicAdd(&test_results.seq1, 1u);
+ } else if ((mem_x_0 == 1u && mem_y_0 == 1u)) {
+ atomicAdd(&test_results.interleaved, 1u);
+ } else if ((mem_x_0 == 2u && mem_y_0 == 2u)) {
+ atomicAdd(&test_results.weak, 1u);
+ }
+ `,
+ TestType.IntraWorkgroup,
+ ResultType.FourBehavior
+ );
+
+ const memModelTester = new MemoryModelTester(
+ t,
+ memoryModelTestParams,
+ testShader,
+ messagePassingResultShader
+ );
+
+ await memModelTester.run(40, 3);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/padding.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/padding.spec.js
new file mode 100644
index 0000000000..40f4431da3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/padding.spec.js
@@ -0,0 +1,425 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Execution Tests for preservation of padding bytes in structures and arrays.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { iterRange } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+/**
+ * Run a shader and check that the buffer output matches expectations.
+ *
+ * @param t The test object
+ * @param wgsl The shader source
+ * @param expected The array of expected values after running the shader
+ */
+function runShaderTest(t, wgsl, expected) {
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({ code: wgsl }),
+ entryPoint: 'main',
+ },
+ });
+
+ // Allocate a buffer and fill it with 0xdeadbeef words.
+ const outputBuffer = t.makeBufferWithContents(
+ new Uint32Array([...iterRange(expected.length, x => 0xdeadbeef)]),
+ GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
+ );
+
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: outputBuffer } }],
+ });
+
+ // Run the shader.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // Check that only the non-padding bytes were modified.
+ t.expectGPUBufferValuesEqual(outputBuffer, expected);
+}
+
+g.test('struct_implicit')
+ .desc(
+ `Test that padding bytes in between structure members are preserved.
+
+ This test defines a structure that has implicit padding and creates a read-write storage
+ buffer with that structure type. The shader assigns the whole variable at once, and we
+ then test that data in the padding bytes was preserved.
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ struct S {
+ a : u32,
+ // 12 bytes of padding
+ b : vec3<u32>,
+ // 4 bytes of padding
+ c : vec2<u32>,
+ // 8 bytes of padding
+ }
+ @group(0) @binding(0) var<storage, read_write> buffer : S;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = S(0x12345678, vec3(0xabcdef01), vec2(0x98765432));
+ }
+ `;
+ runShaderTest(
+ t,
+ wgsl,
+ new Uint32Array([
+ // a : u32
+ 0x12345678,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // b : vec3<u32>
+ 0xabcdef01,
+ 0xabcdef01,
+ 0xabcdef01,
+ 0xdeadbeef,
+ // c : vec2<u32>
+ 0x98765432,
+ 0x98765432,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ ])
+ );
+ });
+
+g.test('struct_explicit')
+ .desc(
+ `Test that padding bytes in between structure members are preserved.
+
+ This test defines a structure with explicit padding attributes and creates a read-write storage
+ buffer with that structure type. The shader assigns the whole variable at once, and we
+ then test that data in the padding bytes was preserved.
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ struct S {
+ a : u32,
+ // 12 bytes of padding
+ @align(16) @size(20) b : u32,
+ // 16 bytes of padding
+ @size(12) c : u32,
+ // 8 bytes of padding
+ }
+ @group(0) @binding(0) var<storage, read_write> buffer : S;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = S(0x12345678, 0xabcdef01, 0x98765432);
+ }
+ `;
+ runShaderTest(
+ t,
+ wgsl,
+ new Uint32Array([
+ // a : u32
+ 0x12345678,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // @align(16) @size(20) b : u32
+ 0xabcdef01,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // @size(12) c : u32
+ 0x98765432,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ ])
+ );
+ });
+
+g.test('struct_nested')
+ .desc(
+ `Test that padding bytes in nested structures are preserved.
+
+ This test defines a set of nested structures that have padding and creates a read-write storage
+ buffer with the root structure type. The shader assigns the whole variable at once, and we
+ then test that data in the padding bytes was preserved.
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ // Size of S1 is 48 bytes.
+ // Alignment of S1 is 16 bytes.
+ struct S1 {
+ a : u32,
+ // 12 bytes of padding
+ b : vec3<u32>,
+ // 4 bytes of padding
+ c : vec2<u32>,
+ // 8 bytes of padding
+ }
+
+ // Size of S2 is 112 bytes.
+ // Alignment of S2 is 48 bytes.
+ struct S2 {
+ a2 : u32,
+ // 12 bytes of padding
+ b2 : S1,
+ c2 : S1,
+ }
+
+ // Size of S3 is 144 bytes.
+ // Alignment of S3 is 48 bytes.
+ struct S3 {
+ a3 : S1,
+ b3 : S2,
+ c3 : S2,
+ }
+
+ @group(0) @binding(0) var<storage, read_write> buffer : S3;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = S3();
+ }
+ `;
+ runShaderTest(
+ t,
+ wgsl,
+ new Uint32Array([
+ // a3 : S1
+ // a3.a1 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // a3.b1 : vec3<u32>
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ // a3.c1 : vec2<u32>
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+
+ // b3 : S2
+ // b3.a2 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // b3.b2 : S1
+ // b3.b2.a1 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // b3.b2.b1 : vec3<u32>
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ // b3.b2.c1 : vec2<u32>
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // b3.c2 : S1
+ // b3.c2.a1 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // b3.c2.b1 : vec3<u32>
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ // b3.c2.c1 : vec2<u32>
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+
+ // c3 : S2
+ // c3.a2 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // c3.b2 : S1
+ // c3.b2.a1 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // c3.b2.b1 : vec3<u32>
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ // c3.b2.c1 : vec2<u32>
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // c3.c2 : S1
+ // c3.c2.a1 : u32
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ // c3.c2.b1 : vec3<u32>
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ // c3.c2.c1 : vec2<u32>
+ 0x00000000,
+ 0x00000000,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ ])
+ );
+ });
+
+g.test('array_of_vec3')
+ .desc(
+ `Test that padding bytes in between array elements are preserved.
+
+ This test defines creates a read-write storage buffer with type array<vec3, 4>. The shader
+ assigns the whole variable at once, and we then test that data in the padding bytes was
+ preserved.
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ @group(0) @binding(0) var<storage, read_write> buffer : array<vec3<u32>, 4>;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = array<vec3<u32>, 4>(
+ vec3(0x12345678),
+ vec3(0xabcdef01),
+ vec3(0x98765432),
+ vec3(0x0f0f0f0f),
+ );
+ }
+ `;
+ runShaderTest(
+ t,
+ wgsl,
+ new Uint32Array([
+ // buffer[0]
+ 0x12345678,
+ 0x12345678,
+ 0x12345678,
+ 0xdeadbeef,
+ // buffer[1]
+ 0xabcdef01,
+ 0xabcdef01,
+ 0xabcdef01,
+ 0xdeadbeef,
+ // buffer[2]
+ 0x98765432,
+ 0x98765432,
+ 0x98765432,
+ 0xdeadbeef,
+ // buffer[2]
+ 0x0f0f0f0f,
+ 0x0f0f0f0f,
+ 0x0f0f0f0f,
+ 0xdeadbeef,
+ ])
+ );
+ });
+
+g.test('array_of_struct')
+ .desc(
+ `Test that padding bytes in between array elements are preserved.
+
+ This test defines creates a read-write storage buffer with type array<S, 4>, where S is a
+ structure that contains padding bytes. The shader assigns the whole variable at once, and we
+ then test that data in the padding bytes was preserved.
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ struct S {
+ a : u32,
+ b : vec3<u32>,
+ }
+ @group(0) @binding(0) var<storage, read_write> buffer : array<S, 3>;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = array<S, 3>(
+ S(0x12345678, vec3(0x0f0f0f0f)),
+ S(0xabcdef01, vec3(0x7c7c7c7c)),
+ S(0x98765432, vec3(0x18181818)),
+ );
+ }
+ `;
+ runShaderTest(
+ t,
+ wgsl,
+ new Uint32Array([
+ // buffer[0]
+ 0x12345678,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0x0f0f0f0f,
+ 0x0f0f0f0f,
+ 0x0f0f0f0f,
+ 0xdeadbeef,
+ // buffer[1]
+ 0xabcdef01,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0x7c7c7c7c,
+ 0x7c7c7c7c,
+ 0x7c7c7c7c,
+ 0xdeadbeef,
+ // buffer[2]
+ 0x98765432,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0xdeadbeef,
+ 0x18181818,
+ 0x18181818,
+ 0x18181818,
+ 0xdeadbeef,
+ ])
+ );
+ });
+
+g.test('vec3')
+ .desc(
+ `Test padding bytes are preserved when assigning to a variable of type vec3 (without a struct).
+ `
+ )
+ .fn(async t => {
+ const wgsl = `
+ @group(0) @binding(0) var<storage, read_write> buffer : vec3<u32>;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ buffer = vec3<u32>(0x12345678, 0xabcdef01, 0x98765432);
+ }
+ `;
+ runShaderTest(t, wgsl, new Uint32Array([0x12345678, 0xabcdef01, 0x98765432, 0xdeadbeef]));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js
new file mode 100644
index 0000000000..160f82750e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access.spec.js
@@ -0,0 +1,472 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests to check datatype clamping in shaders is correctly implemented for all indexable types
+(vectors, matrices, sized/unsized arrays) visible to shaders in various ways.
+
+TODO: add tests to check that textureLoad operations stay in-bounds.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+import { align } from '../../util/math.js';
+import { generateTypes, supportedScalarTypes, supportsAtomics } from '../types.js';
+
+export const g = makeTestGroup(GPUTest);
+
+const kMaxU32 = 0xffff_ffff;
+const kMaxI32 = 0x7fff_ffff;
+const kMinI32 = -0x8000_0000;
+
+/**
+ * Wraps the provided source into a harness that checks calling `runTest()` returns 0.
+ *
+ * Non-test bindings are in bind group 1, including:
+ * - `constants.zero`: a dynamically-uniform `0u` value.
+ */
+function runShaderTest(t, stage, testSource, layout, testBindings, dynamicOffsets) {
+ assert(stage === GPUShaderStage.COMPUTE, 'Only know how to deal with compute for now');
+
+ // Contains just zero (for now).
+ const constantsBuffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.UNIFORM });
+
+ const resultBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ const source = `
+struct Constants {
+ zero: u32
+};
+@group(1) @binding(0) var<uniform> constants: Constants;
+
+struct Result {
+ value: u32
+};
+@group(1) @binding(1) var<storage, read_write> result: Result;
+
+${testSource}
+
+@compute @workgroup_size(1)
+fn main() {
+ _ = constants.zero; // Ensure constants buffer is statically-accessed
+ result.value = runTest();
+}`;
+
+ t.debug(source);
+ const module = t.device.createShaderModule({ code: source });
+ const pipeline = t.device.createComputePipeline({
+ layout,
+ compute: { module, entryPoint: 'main' },
+ });
+
+ const group = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(1),
+ entries: [
+ { binding: 0, resource: { buffer: constantsBuffer } },
+ { binding: 1, resource: { buffer: resultBuffer } },
+ ],
+ });
+
+ const testGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: testBindings,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, testGroup, dynamicOffsets);
+ pass.setBindGroup(1, group);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+
+ t.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(resultBuffer, new Uint32Array([0]));
+}
+
+/** Fill an ArrayBuffer with sentinel values, except clear a region to zero. */
+function testFillArrayBuffer(array, type, { zeroByteStart, zeroByteCount }) {
+ const constructor = { u32: Uint32Array, i32: Int32Array, f32: Float32Array }[type];
+ assert(zeroByteCount % constructor.BYTES_PER_ELEMENT === 0);
+ new constructor(array).fill(42);
+ new constructor(array, zeroByteStart, zeroByteCount / constructor.BYTES_PER_ELEMENT).fill(0);
+}
+
+/**
+ * Generate a bunch of indexable types (vec, mat, sized/unsized array) for testing.
+ */
+
+g.test('linear_memory')
+ .desc(
+ `For each indexable data type (vec, mat, sized/unsized array, of various scalar types), attempts
+ to access (read, write, atomic load/store) a region of memory (buffer or internal) at various
+ (signed/unsigned) indices. Checks that the accesses conform to robust access (OOB reads only
+ return bound memory, OOB writes don't write OOB).
+
+ TODO: Test in/out storage classes.
+ TODO: Test vertex and fragment stages.
+ TODO: Test using a dynamic offset instead of a static offset into uniform/storage bindings.
+ TODO: Test types like vec2<atomic<i32>>, if that's allowed.
+ TODO: Test exprIndexAddon as constexpr.
+ TODO: Test exprIndexAddon as pipeline-overridable constant expression.
+ `
+ )
+ .params(u =>
+ u
+ .combineWithParams([
+ { storageClass: 'storage', storageMode: 'read', access: 'read', dynamicOffset: false },
+ {
+ storageClass: 'storage',
+ storageMode: 'read_write',
+ access: 'read',
+ dynamicOffset: false,
+ },
+ {
+ storageClass: 'storage',
+ storageMode: 'read_write',
+ access: 'write',
+ dynamicOffset: false,
+ },
+ { storageClass: 'storage', storageMode: 'read', access: 'read', dynamicOffset: true },
+ { storageClass: 'storage', storageMode: 'read_write', access: 'read', dynamicOffset: true },
+ {
+ storageClass: 'storage',
+ storageMode: 'read_write',
+ access: 'write',
+ dynamicOffset: true,
+ },
+ { storageClass: 'uniform', access: 'read', dynamicOffset: false },
+ { storageClass: 'uniform', access: 'read', dynamicOffset: true },
+ { storageClass: 'private', access: 'read' },
+ { storageClass: 'private', access: 'write' },
+ { storageClass: 'function', access: 'read' },
+ { storageClass: 'function', access: 'write' },
+ { storageClass: 'workgroup', access: 'read' },
+ { storageClass: 'workgroup', access: 'write' },
+ ])
+ .combineWithParams([
+ { containerType: 'array' },
+ { containerType: 'matrix' },
+ { containerType: 'vector' },
+ ])
+ .combineWithParams([
+ { shadowingMode: 'none' },
+ { shadowingMode: 'module-scope' },
+ { shadowingMode: 'function-scope' },
+ ])
+ .expand('isAtomic', p => (supportsAtomics(p) ? [false, true] : [false]))
+ .beginSubcases()
+ .expand('baseType', supportedScalarTypes)
+ .expandWithParams(generateTypes)
+ )
+ .fn(async t => {
+ const {
+ storageClass,
+ storageMode,
+ access,
+ dynamicOffset,
+ isAtomic,
+ containerType,
+ baseType,
+ type,
+ shadowingMode,
+ _kTypeInfo,
+ } = t.params;
+
+ assert(_kTypeInfo !== undefined, 'not an indexable type');
+ assert('arrayLength' in _kTypeInfo);
+
+ let usesCanary = false;
+ let globalSource = '';
+ let testFunctionSource = '';
+ const testBufferSize = 512;
+ const bufferBindingOffset = 256;
+ /** Undefined if no buffer binding is needed */
+ let bufferBindingSize = undefined;
+
+ // Declare the data that will be accessed to check robust access, as a buffer or a struct
+ // in the global scope or inside the test function itself.
+ const structDecl = `
+struct S {
+ startCanary: array<u32, 10>,
+ data: ${type},
+ endCanary: array<u32, 10>,
+};`;
+
+ const testGroupBGLEntires = [];
+ switch (storageClass) {
+ case 'uniform':
+ case 'storage':
+ {
+ assert(_kTypeInfo.layout !== undefined);
+ const layout = _kTypeInfo.layout;
+ bufferBindingSize = align(layout.size, layout.alignment);
+ const qualifiers = storageClass === 'storage' ? `storage, ${storageMode}` : storageClass;
+ globalSource += `
+struct TestData {
+ data: ${type},
+};
+@group(0) @binding(0) var<${qualifiers}> s: TestData;`;
+
+ testGroupBGLEntires.push({
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: {
+ type:
+ storageClass === 'uniform'
+ ? 'uniform'
+ : storageMode === 'read'
+ ? 'read-only-storage'
+ : 'storage',
+ hasDynamicOffset: dynamicOffset,
+ },
+ });
+ }
+ break;
+
+ case 'private':
+ case 'workgroup':
+ usesCanary = true;
+ globalSource += structDecl;
+ globalSource += `var<${storageClass}> s: S;`;
+ break;
+
+ case 'function':
+ usesCanary = true;
+ globalSource += structDecl;
+ testFunctionSource += 'var s: S;';
+ break;
+ }
+
+ // Build the test function that will do the tests.
+
+ // If we use a local canary declared in the shader, initialize it.
+ if (usesCanary) {
+ testFunctionSource += `
+ for (var i = 0u; i < 10u; i = i + 1u) {
+ s.startCanary[i] = 0xFFFFFFFFu;
+ s.endCanary[i] = 0xFFFFFFFFu;
+ }`;
+ }
+
+ /** Returns a different number each time, kind of like a `__LINE__` to ID the failing check. */
+ const nextErrorReturnValue = (() => {
+ let errorReturnValue = 0x1000;
+ return () => {
+ ++errorReturnValue;
+ return `0x${errorReturnValue.toString(16)}u`;
+ };
+ })();
+
+ // This is here, instead of in subcases, so only a single shader is needed to test many modes.
+ for (const indexSigned of [false, true]) {
+ const indicesToTest = indexSigned
+ ? [
+ // Exactly in bounds (should be OK)
+ '0',
+ `${_kTypeInfo.arrayLength} - 1`,
+ // Exactly out of bounds
+ '-1',
+ `${_kTypeInfo.arrayLength}`,
+ // Far out of bounds
+ '-1000000',
+ '1000000',
+ `${kMinI32}`,
+ `${kMaxI32}`,
+ ]
+ : [
+ // Exactly in bounds (should be OK)
+ '0u',
+ `${_kTypeInfo.arrayLength}u - 1u`,
+ // Exactly out of bounds
+ `${_kTypeInfo.arrayLength}u`,
+ // Far out of bounds
+ '1000000u',
+ `${kMaxU32}u`,
+ `${kMaxI32}u`,
+ ];
+
+ const indexTypeLiteral = indexSigned ? '0' : '0u';
+ const indexTypeCast = indexSigned ? 'i32' : 'u32';
+ for (const exprIndexAddon of [
+ '', // No addon
+ ` + ${indexTypeLiteral}`, // Add a literal 0
+ ` + ${indexTypeCast}(constants.zero)`, // Add a uniform 0
+ ]) {
+ // Produce the accesses to the variable.
+ for (const indexToTest of indicesToTest) {
+ testFunctionSource += `
+ {
+ let index = (${indexToTest})${exprIndexAddon};`;
+ const exprZeroElement = `${_kTypeInfo.elementBaseType}()`;
+ const exprElement = `s.data[index]`;
+
+ switch (access) {
+ case 'read':
+ {
+ let exprLoadElement = isAtomic ? `atomicLoad(&${exprElement})` : exprElement;
+ if (storageClass === 'uniform' && containerType === 'array') {
+ // Scalar types will be wrapped in a vec4 to satisfy array element size
+ // requirements for the uniform address space, so we need an additional index
+ // accessor expression.
+ exprLoadElement += '[0]';
+ }
+ let condition = `${exprLoadElement} != ${exprZeroElement}`;
+ if (containerType === 'matrix') condition = `any(${condition})`;
+ testFunctionSource += `
+ if (${condition}) { return ${nextErrorReturnValue()}; }`;
+ }
+ break;
+
+ case 'write':
+ if (isAtomic) {
+ testFunctionSource += `
+ atomicStore(&s.data[index], ${exprZeroElement});`;
+ } else {
+ testFunctionSource += `
+ s.data[index] = ${exprZeroElement};`;
+ }
+ break;
+ }
+
+ testFunctionSource += `
+ }`;
+ }
+ }
+ }
+
+ // Check that the canaries haven't been modified
+ if (usesCanary) {
+ testFunctionSource += `
+ for (var i = 0u; i < 10u; i = i + 1u) {
+ if (s.startCanary[i] != 0xFFFFFFFFu) {
+ return ${nextErrorReturnValue()};
+ }
+ if (s.endCanary[i] != 0xFFFFFFFFu) {
+ return ${nextErrorReturnValue()};
+ }
+ }`;
+ }
+
+ // Shadowing case declarations
+ let moduleScopeShadowDecls = '';
+ let functionScopeShadowDecls = '';
+
+ switch (shadowingMode) {
+ case 'module-scope':
+ // Shadow the builtins likely used by robustness as module-scope variables
+ moduleScopeShadowDecls = `
+var<private> min = 0;
+var<private> max = 0;
+var<private> arrayLength = 0;
+`;
+ // Make sure that these are referenced by the function.
+ // This ensures that compilers don't strip away unused variables.
+ functionScopeShadowDecls = `
+ _ = min;
+ _ = max;
+ _ = arrayLength;
+`;
+ break;
+ case 'function-scope':
+ // Shadow the builtins likely used by robustness as function-scope variables
+ functionScopeShadowDecls = `
+ let min = 0;
+ let max = 0;
+ let arrayLength = 0;
+`;
+ break;
+ }
+
+ // Run the test
+
+ // First aggregate the test source
+ const testSource = `
+${globalSource}
+${moduleScopeShadowDecls}
+
+fn runTest() -> u32 {
+ ${functionScopeShadowDecls}
+ ${testFunctionSource}
+ return 0u;
+}`;
+
+ const layout = t.device.createPipelineLayout({
+ bindGroupLayouts: [
+ t.device.createBindGroupLayout({
+ entries: testGroupBGLEntires,
+ }),
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: {
+ type: 'uniform',
+ },
+ },
+ {
+ binding: 1,
+ visibility: GPUShaderStage.COMPUTE,
+ buffer: {
+ type: 'storage',
+ },
+ },
+ ],
+ }),
+ ],
+ });
+
+ // Run it.
+ if (bufferBindingSize !== undefined && baseType !== 'bool') {
+ const expectedData = new ArrayBuffer(testBufferSize);
+ const bufferBindingEnd = bufferBindingOffset + bufferBindingSize;
+ testFillArrayBuffer(expectedData, baseType, {
+ zeroByteStart: bufferBindingOffset,
+ zeroByteCount: bufferBindingSize,
+ });
+
+ // Create a buffer that contains zeroes in the allowed access area, and 42s everywhere else.
+ const testBuffer = t.makeBufferWithContents(
+ new Uint8Array(expectedData),
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.COPY_DST
+ );
+
+ // Run the shader, accessing the buffer.
+ runShaderTest(
+ t,
+ GPUShaderStage.COMPUTE,
+ testSource,
+ layout,
+ [
+ {
+ binding: 0,
+ resource: {
+ buffer: testBuffer,
+ offset: dynamicOffset ? 0 : bufferBindingOffset,
+ size: bufferBindingSize,
+ },
+ },
+ ],
+
+ dynamicOffset ? [bufferBindingOffset] : undefined
+ );
+
+ // Check that content of the buffer outside of the allowed area didn't change.
+ const expectedBytes = new Uint8Array(expectedData);
+ t.expectGPUBufferValuesEqual(testBuffer, expectedBytes.subarray(0, bufferBindingOffset), 0);
+ t.expectGPUBufferValuesEqual(
+ testBuffer,
+ expectedBytes.subarray(bufferBindingEnd, testBufferSize),
+ bufferBindingEnd
+ );
+ } else {
+ runShaderTest(t, GPUShaderStage.COMPUTE, testSource, layout, []);
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js
new file mode 100644
index 0000000000..a23948890b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/robust_access_vertex.spec.js
@@ -0,0 +1,553 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Test vertex attributes behave correctly (no crash / data leak) when accessed out of bounds
+
+Test coverage:
+
+The following is parameterized (all combinations tested):
+
+1) Draw call type? (drawIndexed, drawIndirect, drawIndexedIndirect)
+ - Run the draw call using an index buffer and/or an indirect buffer.
+ - Doesn't test direct draw, as vertex buffer OOB are CPU validated and treated as validation errors.
+ - Also the instance step mode vertex buffer OOB are CPU validated for drawIndexed, so we only test
+ robustness access for vertex step mode vertex buffers.
+
+2) Draw call parameter (vertexCount, firstVertex, indexCount, firstIndex, baseVertex, instanceCount,
+ vertexCountInIndexBuffer)
+ - The parameter which goes out of bounds. Filtered depending on the draw call type.
+ - vertexCount, firstVertex: used for drawIndirect only, test for vertex step mode buffer OOB
+ - instanceCount: used for both drawIndirect and drawIndexedIndirect, test for instance step mode buffer OOB
+ - baseVertex, vertexCountInIndexBuffer: used for both drawIndexed and drawIndexedIndirect, test
+ for vertex step mode buffer OOB. vertexCountInIndexBuffer indicates how many vertices are used
+ within the index buffer, i.e. [0, 1, ..., vertexCountInIndexBuffer-1].
+ - indexCount, firstIndex: used for drawIndexedIndirect only, validate the vertex buffer access
+ when the vertex itself is OOB in index buffer. This never happens in drawIndexed as we have index
+ buffer OOB CPU validation for it.
+
+3) Attribute type (float32, float32x2, float32x3, float32x4)
+ - The input attribute type in the vertex shader
+
+4) Error scale (0, 1, 4, 10^2, 10^4, 10^6)
+ - Offset to add to the correct draw call parameter
+ - 0 For control case
+
+5) Additional vertex buffers (0, +4)
+ - Tests that no OOB occurs if more vertex buffers are used
+
+6) Partial last number and offset vertex buffer (false, true)
+ - Tricky cases that make vertex buffer OOB.
+ - With partial last number enabled, vertex buffer size will be 1 byte less than enough, making the
+ last vertex OOB with 1 byte.
+ - Offset vertex buffer will bind the vertex buffer to render pass with 4 bytes offset, causing OOB
+ - For drawIndexed, these two flags are suppressed for instance step mode vertex buffer to make sure
+ it pass the CPU validation.
+
+The tests have one instance step mode vertex buffer bound for instanced attributes, to make sure
+instanceCount / firstInstance are tested.
+
+The tests include multiple attributes per vertex buffer.
+
+The vertex buffers are filled by repeating a few values randomly chosen for each test until the
+end of the buffer.
+
+The tests run a render pipeline which verifies the following:
+1) All vertex attribute values occur in the buffer or are 0 (for control case it can't be 0)
+2) All gl_VertexIndex values are within the index buffer or 0
+
+TODO:
+Currently firstInstance is not tested, as for drawIndexed it is CPU validated, and for drawIndirect
+and drawIndexedIndirect it should always be 0. Once there is an extension to allow making them non-zero,
+it should be added into drawCallTestParameter list.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+
+// Encapsulates a draw call (either indexed or non-indexed)
+class DrawCall {
+ // Add a float offset when binding vertex buffer
+
+ // Keep instance step mode vertex buffer in range, in order to test vertex step
+ // mode buffer OOB in drawIndexed. Setting true will suppress partialLastNumber
+ // and offsetVertexBuffer for instance step mode vertex buffer.
+
+ // Draw
+
+ // DrawIndexed
+ // For generating index buffer in drawIndexed and drawIndexedIndirect
+ // For accessing index buffer in drawIndexed and drawIndexedIndirect
+
+ // Both Draw and DrawIndexed
+
+ constructor({
+ test,
+ vertexArrays,
+ vertexCount,
+ partialLastNumber,
+ offsetVertexBuffer,
+ keepInstanceStepModeBufferInRange,
+ }) {
+ this.test = test;
+
+ // Default arguments (valid call)
+ this.vertexCount = vertexCount;
+ this.firstVertex = 0;
+ this.vertexCountInIndexBuffer = vertexCount;
+ this.indexCount = vertexCount;
+ this.firstIndex = 0;
+ this.baseVertex = 0;
+ this.instanceCount = vertexCount;
+ this.firstInstance = 0;
+
+ this.offsetVertexBuffer = offsetVertexBuffer;
+ this.keepInstanceStepModeBufferInRange = keepInstanceStepModeBufferInRange;
+
+ // Since vertexInIndexBuffer is mutable, generation of the index buffer should be deferred to right before calling draw
+
+ // Generate vertex buffer
+ this.vertexBuffers = vertexArrays.map((v, i) => {
+ if (i === 0 && keepInstanceStepModeBufferInRange) {
+ // Suppress partialLastNumber for the first vertex buffer, aka the instance step mode buffer
+ return this.generateVertexBuffer(v, false);
+ } else {
+ return this.generateVertexBuffer(v, partialLastNumber);
+ }
+ });
+ }
+
+ // Insert a draw call into |pass| with specified type
+ insertInto(pass, indexed, indirect) {
+ if (indexed) {
+ if (indirect) {
+ this.drawIndexedIndirect(pass);
+ } else {
+ this.drawIndexed(pass);
+ }
+ } else {
+ if (indirect) {
+ this.drawIndirect(pass);
+ } else {
+ this.draw(pass);
+ }
+ }
+ }
+
+ // Insert a draw call into |pass|
+ draw(pass) {
+ this.bindVertexBuffers(pass);
+ pass.draw(this.vertexCount, this.instanceCount, this.firstVertex, this.firstInstance);
+ }
+
+ // Insert an indexed draw call into |pass|
+ drawIndexed(pass) {
+ // Generate index buffer
+ const indexArray = new Uint32Array(this.vertexCountInIndexBuffer).map((_, i) => i);
+ const indexBuffer = this.test.makeBufferWithContents(indexArray, GPUBufferUsage.INDEX);
+ this.bindVertexBuffers(pass);
+ pass.setIndexBuffer(indexBuffer, 'uint32');
+ pass.drawIndexed(
+ this.indexCount,
+ this.instanceCount,
+ this.firstIndex,
+ this.baseVertex,
+ this.firstInstance
+ );
+ }
+
+ // Insert an indirect draw call into |pass|
+ drawIndirect(pass) {
+ this.bindVertexBuffers(pass);
+ pass.drawIndirect(this.generateIndirectBuffer(), 0);
+ }
+
+ // Insert an indexed indirect draw call into |pass|
+ drawIndexedIndirect(pass) {
+ // Generate index buffer
+ const indexArray = new Uint32Array(this.vertexCountInIndexBuffer).map((_, i) => i);
+ const indexBuffer = this.test.makeBufferWithContents(indexArray, GPUBufferUsage.INDEX);
+ this.bindVertexBuffers(pass);
+ pass.setIndexBuffer(indexBuffer, 'uint32');
+ pass.drawIndexedIndirect(this.generateIndexedIndirectBuffer(), 0);
+ }
+
+ // Bind all vertex buffers generated
+ bindVertexBuffers(pass) {
+ let currSlot = 0;
+ for (let i = 0; i < this.vertexBuffers.length; i++) {
+ if (i === 0 && this.keepInstanceStepModeBufferInRange) {
+ // Keep the instance step mode buffer in range
+ pass.setVertexBuffer(currSlot++, this.vertexBuffers[i], 0);
+ } else {
+ pass.setVertexBuffer(currSlot++, this.vertexBuffers[i], this.offsetVertexBuffer ? 4 : 0);
+ }
+ }
+ }
+
+ // Create a vertex buffer from |vertexArray|
+ // If |partialLastNumber| is true, delete one byte off the end
+ generateVertexBuffer(vertexArray, partialLastNumber) {
+ let size = vertexArray.byteLength;
+ let length = vertexArray.length;
+ if (partialLastNumber) {
+ size -= 1; // Shave off one byte from the buffer size.
+ length -= 1; // And one whole element from the writeBuffer.
+ }
+ const buffer = this.test.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, // Ensure that buffer can be used by writeBuffer
+ });
+ this.test.device.queue.writeBuffer(buffer, 0, vertexArray.slice(0, length));
+ return buffer;
+ }
+
+ // Create an indirect buffer containing draw call values
+ generateIndirectBuffer() {
+ const indirectArray = new Int32Array([
+ this.vertexCount,
+ this.instanceCount,
+ this.firstVertex,
+ this.firstInstance,
+ ]);
+
+ return this.test.makeBufferWithContents(indirectArray, GPUBufferUsage.INDIRECT);
+ }
+
+ // Create an indirect buffer containing indexed draw call values
+ generateIndexedIndirectBuffer() {
+ const indirectArray = new Int32Array([
+ this.indexCount,
+ this.instanceCount,
+ this.firstIndex,
+ this.baseVertex,
+ this.firstInstance,
+ ]);
+
+ return this.test.makeBufferWithContents(indirectArray, GPUBufferUsage.INDIRECT);
+ }
+}
+
+// Parameterize different sized types
+
+const typeInfoMap = {
+ float32: {
+ wgslType: 'f32',
+ sizeInBytes: 4,
+ validationFunc: 'return valid(v);',
+ },
+ float32x2: {
+ wgslType: 'vec2<f32>',
+ sizeInBytes: 8,
+ validationFunc: 'return valid(v.x) && valid(v.y);',
+ },
+ float32x3: {
+ wgslType: 'vec3<f32>',
+ sizeInBytes: 12,
+ validationFunc: 'return valid(v.x) && valid(v.y) && valid(v.z);',
+ },
+ float32x4: {
+ wgslType: 'vec4<f32>',
+ sizeInBytes: 16,
+ validationFunc: `return (valid(v.x) && valid(v.y) && valid(v.z) && valid(v.w)) ||
+ (v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && (v.w == 0.0 || v.w == 1.0));`,
+ },
+};
+
+class F extends GPUTest {
+ generateBufferContents(numVertices, attributesPerBuffer, typeInfo, arbitraryValues, bufferCount) {
+ // Make an array big enough for the vertices, attributes, and size of each element
+ const vertexArray = new Float32Array(
+ numVertices * attributesPerBuffer * (typeInfo.sizeInBytes / 4)
+ );
+
+ for (let i = 0; i < vertexArray.length; ++i) {
+ vertexArray[i] = arbitraryValues[i % arbitraryValues.length];
+ }
+
+ // Only the first buffer is instance step mode, all others are vertex step mode buffer
+ assert(bufferCount >= 2);
+ const bufferContents = [];
+ for (let i = 0; i < bufferCount; i++) {
+ bufferContents.push(vertexArray);
+ }
+
+ return bufferContents;
+ }
+
+ generateVertexBufferDescriptors(bufferCount, attributesPerBuffer, format) {
+ const typeInfo = typeInfoMap[format];
+ // Vertex buffer descriptors
+ const buffers = [];
+ {
+ let currAttribute = 0;
+ for (let i = 0; i < bufferCount; i++) {
+ buffers.push({
+ arrayStride: attributesPerBuffer * typeInfo.sizeInBytes,
+ stepMode: i === 0 ? 'instance' : 'vertex',
+ attributes: Array(attributesPerBuffer)
+ .fill(0)
+ .map((_, i) => ({
+ shaderLocation: currAttribute++,
+ offset: i * typeInfo.sizeInBytes,
+ format,
+ })),
+ });
+ }
+ }
+ return buffers;
+ }
+
+ generateVertexShaderCode({
+ bufferCount,
+ attributesPerBuffer,
+ validValues,
+ typeInfo,
+ vertexIndexOffset,
+ numVertices,
+ isIndexed,
+ }) {
+ // Create layout and attributes listing
+ let layoutStr = 'struct Attributes {';
+ const attributeNames = [];
+ {
+ let currAttribute = 0;
+ for (let i = 0; i < bufferCount; i++) {
+ for (let j = 0; j < attributesPerBuffer; j++) {
+ layoutStr += `@location(${currAttribute}) a_${currAttribute} : ${typeInfo.wgslType},\n`;
+ attributeNames.push(`a_${currAttribute}`);
+ currAttribute++;
+ }
+ }
+ }
+ layoutStr += '};';
+
+ const vertexShaderCode = `
+ ${layoutStr}
+
+ fn valid(f : f32) -> bool {
+ return ${validValues.map(v => `f == ${v}.0`).join(' || ')};
+ }
+
+ fn validationFunc(v : ${typeInfo.wgslType}) -> bool {
+ ${typeInfo.validationFunc}
+ }
+
+ @vertex fn main(
+ @builtin(vertex_index) VertexIndex : u32,
+ attributes : Attributes
+ ) -> @builtin(position) vec4<f32> {
+ var attributesInBounds = ${attributeNames
+ .map(a => `validationFunc(attributes.${a})`)
+ .join(' && ')};
+
+ var indexInBoundsCountFromBaseVertex =
+ (VertexIndex >= ${vertexIndexOffset}u &&
+ VertexIndex < ${vertexIndexOffset + numVertices}u);
+ var indexInBounds = VertexIndex == 0u || indexInBoundsCountFromBaseVertex;
+
+ var Position : vec4<f32>;
+ if (attributesInBounds && (${!isIndexed} || indexInBounds)) {
+ // Success case, move the vertex to the right of the viewport to show that at least one case succeed
+ Position = vec4<f32>(0.5, 0.0, 0.0, 1.0);
+ } else {
+ // Failure case, move the vertex to the left of the viewport
+ Position = vec4<f32>(-0.5, 0.0, 0.0, 1.0);
+ }
+ return Position;
+ }`;
+ return vertexShaderCode;
+ }
+
+ createRenderPipeline({
+ bufferCount,
+ attributesPerBuffer,
+ validValues,
+ typeInfo,
+ vertexIndexOffset,
+ numVertices,
+ isIndexed,
+ buffers,
+ }) {
+ const pipeline = this.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: this.device.createShaderModule({
+ code: this.generateVertexShaderCode({
+ bufferCount,
+ attributesPerBuffer,
+ validValues,
+ typeInfo,
+ vertexIndexOffset,
+ numVertices,
+ isIndexed,
+ }),
+ }),
+ entryPoint: 'main',
+ buffers,
+ },
+ fragment: {
+ module: this.device.createShaderModule({
+ code: `
+ @fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ primitive: { topology: 'point-list' },
+ });
+ return pipeline;
+ }
+
+ doTest({
+ bufferCount,
+ attributesPerBuffer,
+ dataType,
+ validValues,
+ vertexIndexOffset,
+ numVertices,
+ isIndexed,
+ isIndirect,
+ drawCall,
+ }) {
+ // Vertex buffer descriptors
+ const buffers = this.generateVertexBufferDescriptors(
+ bufferCount,
+ attributesPerBuffer,
+ dataType
+ );
+
+ // Pipeline setup, texture setup
+ const pipeline = this.createRenderPipeline({
+ bufferCount,
+ attributesPerBuffer,
+ validValues,
+ typeInfo: typeInfoMap[dataType],
+ vertexIndexOffset,
+ numVertices,
+ isIndexed,
+ buffers,
+ });
+
+ const colorAttachment = this.device.createTexture({
+ format: 'rgba8unorm',
+ size: { width: 2, height: 1, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const colorAttachmentView = colorAttachment.createView();
+
+ const encoder = this.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ storeOp: 'store',
+ clearValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+
+ // Run the draw variant
+ drawCall.insertInto(pass, isIndexed, isIndirect);
+
+ pass.end();
+ this.device.queue.submit([encoder.finish()]);
+
+ // Validate we see green on the left pixel, showing that no failure case is detected
+ this.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ 'rgba8unorm',
+ { x: 0, y: 0 },
+ { exp: new Uint8Array([0x00, 0xff, 0x00, 0xff]), layout: { mipLevel: 0 } }
+ );
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('vertex_buffer_access')
+ .params(
+ u =>
+ u
+ .combineWithParams([
+ { indexed: false, indirect: true },
+ { indexed: true, indirect: false },
+ { indexed: true, indirect: true },
+ ])
+ .expand('drawCallTestParameter', function* (p) {
+ if (p.indexed) {
+ yield* ['baseVertex', 'vertexCountInIndexBuffer'];
+ if (p.indirect) {
+ yield* ['indexCount', 'instanceCount', 'firstIndex'];
+ }
+ } else if (p.indirect) {
+ yield* ['vertexCount', 'instanceCount', 'firstVertex'];
+ }
+ })
+ .combine('type', Object.keys(typeInfoMap))
+ .combine('additionalBuffers', [0, 4])
+ .combine('partialLastNumber', [false, true])
+ .combine('offsetVertexBuffer', [false, true])
+ .combine('errorScale', [0, 1, 4, 10 ** 2, 10 ** 4, 10 ** 6])
+ .unless(p => p.drawCallTestParameter === 'instanceCount' && p.errorScale > 10 ** 4) // To avoid timeout
+ )
+ .fn(async t => {
+ const p = t.params;
+ const typeInfo = typeInfoMap[p.type];
+
+ // Number of vertices to draw
+ const numVertices = 4;
+ // Each buffer is bound to this many attributes (2 would mean 2 attributes per buffer)
+ const attributesPerBuffer = 2;
+ // Some arbitrary values to fill our buffer with to avoid collisions with other tests
+ const arbitraryValues = [990, 685, 446, 175];
+
+ // A valid value is 0 or one in the buffer
+ const validValues =
+ p.errorScale === 0 && !p.offsetVertexBuffer && !p.partialLastNumber
+ ? arbitraryValues // Control case with no OOB access, must read back valid values in buffer
+ : [0, ...arbitraryValues]; // Testing case with OOB access, can be 0 for OOB data
+
+ // Generate vertex buffer contents. Only the first buffer is instance step mode, all others are vertex step mode
+ const bufferCount = p.additionalBuffers + 2; // At least one instance step mode and one vertex step mode buffer
+ const bufferContents = t.generateBufferContents(
+ numVertices,
+ attributesPerBuffer,
+ typeInfo,
+ arbitraryValues,
+ bufferCount
+ );
+
+ // Mutable draw call
+ const draw = new DrawCall({
+ test: t,
+ vertexArrays: bufferContents,
+ vertexCount: numVertices,
+ partialLastNumber: p.partialLastNumber,
+ offsetVertexBuffer: p.offsetVertexBuffer,
+ keepInstanceStepModeBufferInRange: p.indexed && !p.indirect, // keep instance step mode buffer in range for drawIndexed
+ });
+
+ // Offset the draw call parameter we are testing by |errorScale|
+ draw[p.drawCallTestParameter] += p.errorScale;
+ // Offset the range checks for gl_VertexIndex in the shader if we use BaseVertex
+ let vertexIndexOffset = 0;
+ if (p.drawCallTestParameter === 'baseVertex') {
+ vertexIndexOffset += p.errorScale;
+ }
+
+ t.doTest({
+ bufferCount,
+ attributesPerBuffer,
+ dataType: p.type,
+ validValues,
+ vertexIndexOffset,
+ numVertices,
+ isIndexed: p.indexed,
+ isIndirect: p.indirect,
+ drawCall: draw,
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js
new file mode 100644
index 0000000000..6e128126af
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/compute_builtins.spec.js
@@ -0,0 +1,294 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Test compute shader builtin variables`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { iterRange } from '../../../../common/util/util.js';
+import { GPUTest } from '../../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// Test that the values for each input builtin are correct.
+g.test('inputs')
+ .desc(`Test compute shader builtin inputs values`)
+ .params(u =>
+ u
+ .combine('method', ['param', 'struct', 'mixed'])
+ .combine('dispatch', ['direct', 'indirect'])
+ .combineWithParams([
+ {
+ groupSize: { x: 1, y: 1, z: 1 },
+ numGroups: { x: 1, y: 1, z: 1 },
+ },
+ {
+ groupSize: { x: 8, y: 4, z: 2 },
+ numGroups: { x: 1, y: 1, z: 1 },
+ },
+ {
+ groupSize: { x: 1, y: 1, z: 1 },
+ numGroups: { x: 8, y: 4, z: 2 },
+ },
+ {
+ groupSize: { x: 3, y: 7, z: 5 },
+ numGroups: { x: 13, y: 9, z: 11 },
+ },
+ ])
+ .beginSubcases()
+ )
+ .fn(async t => {
+ const invocationsPerGroup = t.params.groupSize.x * t.params.groupSize.y * t.params.groupSize.z;
+ const totalInvocations =
+ invocationsPerGroup * t.params.numGroups.x * t.params.numGroups.y * t.params.numGroups.z;
+
+ // Generate the structures, parameters, and builtin expressions used in the shader.
+ let params = '';
+ let structures = '';
+ let local_id = '';
+ let local_index = '';
+ let global_id = '';
+ let group_id = '';
+ let num_groups = '';
+ switch (t.params.method) {
+ case 'param':
+ params = `
+ @builtin(local_invocation_id) local_id : vec3<u32>,
+ @builtin(local_invocation_index) local_index : u32,
+ @builtin(global_invocation_id) global_id : vec3<u32>,
+ @builtin(workgroup_id) group_id : vec3<u32>,
+ @builtin(num_workgroups) num_groups : vec3<u32>,
+ `;
+ local_id = 'local_id';
+ local_index = 'local_index';
+ global_id = 'global_id';
+ group_id = 'group_id';
+ num_groups = 'num_groups';
+ break;
+ case 'struct':
+ structures = `struct Inputs {
+ @builtin(local_invocation_id) local_id : vec3<u32>,
+ @builtin(local_invocation_index) local_index : u32,
+ @builtin(global_invocation_id) global_id : vec3<u32>,
+ @builtin(workgroup_id) group_id : vec3<u32>,
+ @builtin(num_workgroups) num_groups : vec3<u32>,
+ };`;
+ params = `inputs : Inputs`;
+ local_id = 'inputs.local_id';
+ local_index = 'inputs.local_index';
+ global_id = 'inputs.global_id';
+ group_id = 'inputs.group_id';
+ num_groups = 'inputs.num_groups';
+ break;
+ case 'mixed':
+ structures = `struct InputsA {
+ @builtin(local_invocation_index) local_index : u32,
+ @builtin(global_invocation_id) global_id : vec3<u32>,
+ };
+ struct InputsB {
+ @builtin(workgroup_id) group_id : vec3<u32>
+ };`;
+ params = `@builtin(local_invocation_id) local_id : vec3<u32>,
+ inputsA : InputsA,
+ inputsB : InputsB,
+ @builtin(num_workgroups) num_groups : vec3<u32>,`;
+ local_id = 'local_id';
+ local_index = 'inputsA.local_index';
+ global_id = 'inputsA.global_id';
+ group_id = 'inputsB.group_id';
+ num_groups = 'num_groups';
+ break;
+ }
+
+ // WGSL shader that stores every builtin value to a buffer, for every invocation in the grid.
+ const wgsl = `
+ struct S {
+ data : array<u32>
+ };
+ struct V {
+ data : array<vec3<u32>>
+ };
+ @group(0) @binding(0) var<storage, read_write> local_id_out : V;
+ @group(0) @binding(1) var<storage, read_write> local_index_out : S;
+ @group(0) @binding(2) var<storage, read_write> global_id_out : V;
+ @group(0) @binding(3) var<storage, read_write> group_id_out : V;
+ @group(0) @binding(4) var<storage, read_write> num_groups_out : V;
+
+ ${structures}
+
+ const group_width = ${t.params.groupSize.x}u;
+ const group_height = ${t.params.groupSize.y}u;
+ const group_depth = ${t.params.groupSize.z}u;
+
+ @compute @workgroup_size(group_width, group_height, group_depth)
+ fn main(
+ ${params}
+ ) {
+ let group_index = ((${group_id}.z * ${num_groups}.y) + ${group_id}.y) * ${num_groups}.x + ${group_id}.x;
+ let global_index = group_index * ${invocationsPerGroup}u + ${local_index};
+ local_id_out.data[global_index] = ${local_id};
+ local_index_out.data[global_index] = ${local_index};
+ global_id_out.data[global_index] = ${global_id};
+ group_id_out.data[global_index] = ${group_id};
+ num_groups_out.data[global_index] = ${num_groups};
+ }
+ `;
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: wgsl,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ // Helper to create a `size`-byte buffer with binding number `binding`.
+ function createBuffer(size, binding) {
+ const buffer = t.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(buffer);
+
+ bindGroupEntries.push({
+ binding,
+ resource: {
+ buffer,
+ },
+ });
+
+ return buffer;
+ }
+
+ // Create the output buffers.
+ const bindGroupEntries = [];
+ const localIdBuffer = createBuffer(totalInvocations * 16, 0);
+ const localIndexBuffer = createBuffer(totalInvocations * 4, 1);
+ const globalIdBuffer = createBuffer(totalInvocations * 16, 2);
+ const groupIdBuffer = createBuffer(totalInvocations * 16, 3);
+ const numGroupsBuffer = createBuffer(totalInvocations * 16, 4);
+
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: bindGroupEntries,
+ });
+
+ // Run the shader.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ switch (t.params.dispatch) {
+ case 'direct':
+ pass.dispatchWorkgroups(t.params.numGroups.x, t.params.numGroups.y, t.params.numGroups.z);
+ break;
+ case 'indirect': {
+ const dispatchBuffer = t.device.createBuffer({
+ size: 3 * Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.INDIRECT,
+ mappedAtCreation: true,
+ });
+ t.trackForCleanup(dispatchBuffer);
+ const dispatchData = new Uint32Array(dispatchBuffer.getMappedRange());
+ dispatchData[0] = t.params.numGroups.x;
+ dispatchData[1] = t.params.numGroups.y;
+ dispatchData[2] = t.params.numGroups.z;
+ dispatchBuffer.unmap();
+ pass.dispatchWorkgroupsIndirect(dispatchBuffer, 0);
+ break;
+ }
+ }
+
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // Helper to check that the vec3<u32> value at each index of the provided `output` buffer
+ // matches the expected value for that invocation, as generated by the `getBuiltinValue`
+ // function. The `name` parameter is the builtin name, used for error messages.
+ const checkEachIndex = (output, name, getBuiltinValue) => {
+ // Loop over workgroups.
+ for (let gz = 0; gz < t.params.numGroups.z; gz++) {
+ for (let gy = 0; gy < t.params.numGroups.y; gy++) {
+ for (let gx = 0; gx < t.params.numGroups.x; gx++) {
+ // Loop over invocations within a group.
+ for (let lz = 0; lz < t.params.groupSize.z; lz++) {
+ for (let ly = 0; ly < t.params.groupSize.y; ly++) {
+ for (let lx = 0; lx < t.params.groupSize.x; lx++) {
+ const groupIndex = (gz * t.params.numGroups.y + gy) * t.params.numGroups.x + gx;
+ const localIndex = (lz * t.params.groupSize.y + ly) * t.params.groupSize.x + lx;
+ const globalIndex = groupIndex * invocationsPerGroup + localIndex;
+ const expected = getBuiltinValue(
+ { x: gx, y: gy, z: gz },
+ { x: lx, y: ly, z: lz }
+ );
+
+ if (output[globalIndex * 4 + 0] !== expected.x) {
+ return new Error(
+ `${name}.x failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` +
+ ` expected: ${expected.x}\n` +
+ ` got: ${output[globalIndex * 4 + 0]}`
+ );
+ }
+ if (output[globalIndex * 4 + 1] !== expected.y) {
+ return new Error(
+ `${name}.y failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` +
+ ` expected: ${expected.y}\n` +
+ ` got: ${output[globalIndex * 4 + 1]}`
+ );
+ }
+ if (output[globalIndex * 4 + 2] !== expected.z) {
+ return new Error(
+ `${name}.z failed at group(${gx},${gy},${gz}) local(${lx},${ly},${lz}))\n` +
+ ` expected: ${expected.z}\n` +
+ ` got: ${output[globalIndex * 4 + 2]}`
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return undefined;
+ };
+
+ // Check @builtin(local_invocation_index) values.
+ t.expectGPUBufferValuesEqual(
+ localIndexBuffer,
+ new Uint32Array([...iterRange(totalInvocations, x => x % invocationsPerGroup)])
+ );
+
+ // Check @builtin(local_invocation_id) values.
+ t.expectGPUBufferValuesPassCheck(
+ localIdBuffer,
+ outputData => checkEachIndex(outputData, 'local_invocation_id', (_, localId) => localId),
+ { type: Uint32Array, typedLength: totalInvocations * 4 }
+ );
+
+ // Check @builtin(global_invocation_id) values.
+ const getGlobalId = (groupId, localId) => {
+ return {
+ x: groupId.x * t.params.groupSize.x + localId.x,
+ y: groupId.y * t.params.groupSize.y + localId.y,
+ z: groupId.z * t.params.groupSize.z + localId.z,
+ };
+ };
+ t.expectGPUBufferValuesPassCheck(
+ globalIdBuffer,
+ outputData => checkEachIndex(outputData, 'global_invocation_id', getGlobalId),
+ { type: Uint32Array, typedLength: totalInvocations * 4 }
+ );
+
+ // Check @builtin(workgroup_id) values.
+ t.expectGPUBufferValuesPassCheck(
+ groupIdBuffer,
+ outputData => checkEachIndex(outputData, 'workgroup_id', (groupId, _) => groupId),
+ { type: Uint32Array, typedLength: totalInvocations * 4 }
+ );
+
+ // Check @builtin(num_workgroups) values.
+ t.expectGPUBufferValuesPassCheck(
+ numGroupsBuffer,
+ outputData => checkEachIndex(outputData, 'num_workgroups', () => t.params.numGroups),
+ { type: Uint32Array, typedLength: totalInvocations * 4 }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/shared_structs.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/shared_structs.spec.js
new file mode 100644
index 0000000000..73c6af6745
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/shader_io/shared_structs.spec.js
@@ -0,0 +1,356 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Test the shared use of structures containing entry point IO attributes`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { checkElementsEqual } from '../../../util/check_contents.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('shared_with_buffer')
+ .desc(
+ `Test sharing an entry point IO struct with a buffer.
+
+ This test defines a structure that contains both builtin attributes and layout attributes,
+ and uses that structure as both an entry point input and the store type of a storage buffer.
+ The builtin attributes should be ignored when used for the storage buffer, and the layout
+ attributes should be ignored when used as an entry point IO parameter.
+ `
+ )
+ .fn(async t => {
+ // Set the dispatch parameters such that we get some interesting (non-zero) built-in variables.
+ const wgsize = new Uint32Array([8, 4, 2]);
+ const numGroups = new Uint32Array([4, 2, 8]);
+
+ // Pick a single invocation to copy the input structure to the output buffer.
+ const targetLocalIndex = 13;
+ const targetGroup = new Uint32Array([2, 1, 5]);
+
+ // The test shader defines a structure that contains members decorated with built-in variable
+ // attributes, and also layout attributes for the storage buffer.
+ const wgsl = `
+ struct S {
+ /* byte offset: 0 */ @size(32) @builtin(workgroup_id) group_id : vec3<u32>,
+ /* byte offset: 32 */ @builtin(local_invocation_index) local_index : u32,
+ /* byte offset: 64 */ @align(64) @builtin(num_workgroups) numGroups : vec3<u32>,
+ };
+
+ @group(0) @binding(0)
+ var<storage, read_write> outputs : S;
+
+ @compute @workgroup_size(${wgsize[0]}, ${wgsize[1]}, ${wgsize[2]})
+ fn main(inputs : S) {
+ if (inputs.group_id.x == ${targetGroup[0]}u &&
+ inputs.group_id.y == ${targetGroup[1]}u &&
+ inputs.group_id.z == ${targetGroup[2]}u &&
+ inputs.local_index == ${targetLocalIndex}u) {
+ outputs = inputs;
+ }
+ }
+ `;
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({ code: wgsl }),
+ entryPoint: 'main',
+ },
+ });
+
+ // Allocate a buffer to hold the output structure.
+ const bufferNumElements = 32;
+ const outputBuffer = t.device.createBuffer({
+ size: bufferNumElements * Uint32Array.BYTES_PER_ELEMENT,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer: outputBuffer } }],
+ });
+
+ // Run the shader.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(numGroups[0], numGroups[1], numGroups[2]);
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // Check the output values.
+ const checkOutput = outputs => {
+ if (checkElementsEqual(outputs.slice(0, 3), targetGroup)) {
+ return new Error(
+ `group_id comparison failed\n` +
+ ` expected: ${targetGroup}\n` +
+ ` got: ${outputs.slice(0, 3)}`
+ );
+ }
+ if (outputs[8] !== targetLocalIndex) {
+ return new Error(
+ `local_index comparison failed\n` +
+ ` expected: ${targetLocalIndex}\n` +
+ ` got: ${outputs[8]}`
+ );
+ }
+ if (checkElementsEqual(outputs.slice(16, 19), numGroups)) {
+ return new Error(
+ `numGroups comparison failed\n` +
+ ` expected: ${numGroups}\n` +
+ ` got: ${outputs.slice(16, 19)}`
+ );
+ }
+ return undefined;
+ };
+ t.expectGPUBufferValuesPassCheck(outputBuffer, outputData => checkOutput(outputData), {
+ type: Uint32Array,
+ typedLength: bufferNumElements,
+ });
+ });
+
+g.test('shared_between_stages')
+ .desc(
+ `Test sharing an entry point IO struct between different pipeline stages.
+
+ This test defines an entry point IO structure, and uses it as both the output of a vertex
+ shader and the input to a fragment shader.
+ `
+ )
+ .fn(async t => {
+ const size = [31, 31];
+ const wgsl = `
+ struct Interface {
+ @builtin(position) position : vec4<f32>,
+ @location(0) color : f32,
+ };
+
+ var<private> vertices : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-0.7, -0.7),
+ vec2<f32>( 0.0, 0.7),
+ vec2<f32>( 0.7, -0.7),
+ );
+
+ @vertex
+ fn vert_main(@builtin(vertex_index) index : u32) -> Interface {
+ return Interface(vec4<f32>(vertices[index], 0.0, 1.0), 1.0);
+ }
+
+ @fragment
+ fn frag_main(inputs : Interface) -> @location(0) vec4<f32> {
+ // Toggle red vs green based on the x position.
+ var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ if (inputs.position.x > f32(${size[0] / 2})) {
+ color.r = inputs.color;
+ } else {
+ color.g = inputs.color;
+ }
+ return color;
+ }
+ `;
+
+ // Set up the render pipeline.
+ const module = t.device.createShaderModule({ code: wgsl });
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'vert_main',
+ },
+ fragment: {
+ module,
+ entryPoint: 'frag_main',
+ targets: [
+ {
+ format: 'rgba8unorm',
+ },
+ ],
+ },
+ });
+
+ // Draw a red triangle.
+ const renderTarget = t.device.createTexture({
+ size,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ format: 'rgba8unorm',
+ });
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // Test a few points to make sure we rendered a half-red/half-green triangle.
+ const redPixel = new Uint8Array([255, 0, 0, 255]);
+ const greenPixel = new Uint8Array([0, 255, 0, 255]);
+ for (const p of [
+ { x: 16, y: 15 },
+ { x: 16, y: 15 },
+ { x: 22, y: 20 },
+ ]) {
+ t.expectSinglePixelIn2DTexture(renderTarget, 'rgba8unorm', p, {
+ exp: redPixel,
+ });
+ }
+ for (const p of [
+ { x: 14, y: 15 },
+ { x: 14, y: 8 },
+ { x: 8, y: 20 },
+ ]) {
+ t.expectSinglePixelIn2DTexture(renderTarget, 'rgba8unorm', p, {
+ exp: greenPixel,
+ });
+ }
+ const blackPixel = new Uint8Array([0, 0, 0, 0]);
+ for (const p of [
+ { x: 2, y: 2 },
+ { x: 2, y: 28 },
+ { x: 28, y: 2 },
+ { x: 28, y: 28 },
+ ]) {
+ t.expectSinglePixelIn2DTexture(renderTarget, 'rgba8unorm', p, {
+ exp: blackPixel,
+ });
+ }
+ });
+
+g.test('shared_with_non_entry_point_function')
+ .desc(
+ `Test sharing an entry point IO struct with a non entry point function.
+
+ This test defines structures that contain builtin and location attributes, and uses those
+ structures as parameter and return types for entry point functions and regular functions.
+ `
+ )
+ .fn(async t => {
+ // The test shader defines structures that contain members decorated with built-in variable
+ // attributes and user-defined IO. These structures are passed to and returned from regular
+ // functions.
+ const wgsl = `
+ struct Inputs {
+ @builtin(vertex_index) index : u32,
+ @location(0) color : vec4<f32>,
+ };
+ struct Outputs {
+ @builtin(position) position : vec4<f32>,
+ @location(0) color : vec4<f32>,
+ };
+
+ var<private> vertices : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
+ vec2<f32>(-0.7, -0.7),
+ vec2<f32>( 0.0, 0.7),
+ vec2<f32>( 0.7, -0.7),
+ );
+
+ fn process(in : Inputs) -> Outputs {
+ var out : Outputs;
+ out.position = vec4<f32>(vertices[in.index], 0.0, 1.0);
+ out.color = in.color;
+ return out;
+ }
+
+ @vertex
+ fn vert_main(inputs : Inputs) -> Outputs {
+ return process(inputs);
+ }
+
+ @fragment
+ fn frag_main(@location(0) color : vec4<f32>) -> @location(0) vec4<f32> {
+ return color;
+ }
+ `;
+
+ // Set up the render pipeline.
+ const module = t.device.createShaderModule({ code: wgsl });
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'vert_main',
+ buffers: [
+ {
+ attributes: [
+ {
+ shaderLocation: 0,
+ format: 'float32x4',
+ offset: 0,
+ },
+ ],
+
+ arrayStride: 4 * Float32Array.BYTES_PER_ELEMENT,
+ },
+ ],
+ },
+ fragment: {
+ module,
+ entryPoint: 'frag_main',
+ targets: [
+ {
+ format: 'rgba8unorm',
+ },
+ ],
+ },
+ });
+
+ // Draw a triangle.
+ // The vertex buffer contains the vertex colors (all red).
+ const vertexBuffer = t.makeBufferWithContents(
+ new Float32Array([1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0]),
+ GPUBufferUsage.VERTEX
+ );
+
+ const renderTarget = t.device.createTexture({
+ size: [31, 31],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ format: 'rgba8unorm',
+ });
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: [0, 0, 0, 0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.setVertexBuffer(0, vertexBuffer);
+ pass.draw(3);
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+
+ // Test a few points to make sure we rendered a red triangle.
+ const redPixel = new Uint8Array([255, 0, 0, 255]);
+ for (const p of [
+ { x: 15, y: 15 },
+ { x: 15, y: 8 },
+ { x: 8, y: 20 },
+ { x: 22, y: 20 },
+ ]) {
+ t.expectSinglePixelIn2DTexture(renderTarget, 'rgba8unorm', p, {
+ exp: redPixel,
+ });
+ }
+ const blackPixel = new Uint8Array([0, 0, 0, 0]);
+ for (const p of [
+ { x: 2, y: 2 },
+ { x: 2, y: 28 },
+ { x: 28, y: 2 },
+ { x: 28, y: 28 },
+ ]) {
+ t.expectSinglePixelIn2DTexture(renderTarget, 'rgba8unorm', p, {
+ exp: blackPixel,
+ });
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js
new file mode 100644
index 0000000000..aa64e67c2b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/execution/zero_init.spec.js
@@ -0,0 +1,434 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Test that variables in the shader are zero initialized`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { unreachable } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+import {
+ kVectorContainerTypes,
+ kMatrixContainerTypes,
+ supportedScalarTypes,
+ supportsAtomics,
+} from '../types.js';
+
+function prettyPrint(t) {
+ switch (t.type) {
+ case 'container':
+ switch (t.containerType) {
+ case 'array':
+ return `array<${prettyPrint(t.elementType)}, ${t.length}>`;
+ case 'struct':
+ return `struct { ${t.members.map(m => prettyPrint(m)).join(', ')} }`;
+ default:
+ return `${t.containerType}<${prettyPrint({
+ type: 'scalar',
+ scalarType: t.scalarType,
+ isAtomic: false,
+ })}>`;
+ }
+
+ break;
+ case 'scalar':
+ if (t.isAtomic) {
+ return `atomic<${t.scalarType}>`;
+ }
+ return t.scalarType;
+ }
+}
+
+export const g = makeTestGroup(GPUTest);
+g.test('compute,zero_init')
+ .desc(
+ `Test that uninitialized variables in workgroup, private, and function storage classes are initialized to zero.
+
+ TODO: Run a shader before the test to attempt to fill memory with garbage`
+ )
+ .params(u =>
+ u
+ // Only workgroup, function, and private variables can be declared without data bound to them.
+ // The implementation's shader translator should ensure these values are initialized.
+ .combine('storageClass', ['workgroup', 'private', 'function'])
+ .expand('workgroupSize', ({ storageClass }) => {
+ switch (storageClass) {
+ case 'workgroup':
+ return [
+ [1, 1, 1],
+ [1, 32, 1],
+ [64, 1, 1],
+ [1, 1, 48],
+ [1, 47, 1],
+ [33, 1, 1],
+ [1, 1, 63],
+ [8, 8, 2],
+ [7, 7, 3],
+ ];
+
+ case 'function':
+ case 'private':
+ return [[1, 1, 1]];
+ }
+ })
+ .beginSubcases()
+ // Fewer subcases: Only 0 and 2. If double-nested containers work, single-nested should too.
+ .combine('_containerDepth', [0, 2])
+ .expandWithParams(function* (p) {
+ const kElementCounts = [
+ [], // Not used. Depth 0 is always scalars.
+ [1, 3, 67], // Test something above the workgroup size.
+ [1, 3],
+ ];
+
+ const kMemberCounts = [1, 3];
+
+ const memoizedTypes = [];
+
+ function generateTypesMemo(depth) {
+ if (memoizedTypes[depth] === undefined) {
+ memoizedTypes[depth] = Array.from(generateTypes(depth));
+ }
+ return memoizedTypes[depth];
+ }
+
+ function* generateTypes(depth) {
+ if (depth === 0) {
+ for (const isAtomic of supportsAtomics({
+ ...p,
+ access: 'read_write',
+ storageMode: undefined,
+ containerType: 'scalar',
+ })
+ ? [true, false]
+ : [false]) {
+ for (const scalarType of supportedScalarTypes({ isAtomic, ...p })) {
+ // Fewer subcases: For nested types, skip atomic u32 and non-atomic i32.
+ if (p._containerDepth > 0) {
+ if (scalarType === 'u32' && isAtomic) continue;
+ if (scalarType === 'i32' && !isAtomic) continue;
+ }
+
+ yield {
+ type: 'scalar',
+ scalarType,
+ isAtomic,
+ };
+ if (!isAtomic) {
+ // Vector types
+ for (const vectorType of kVectorContainerTypes) {
+ // Fewer subcases: For nested types, only include
+ // vec2<u32>, vec3<i32>, and vec4<f32>
+ if (p._containerDepth > 0) {
+ if (
+ !(
+ (vectorType === 'vec2' && scalarType === 'u32') ||
+ (vectorType === 'vec3' && scalarType === 'i32') ||
+ (vectorType === 'vec4' && scalarType === 'f32')
+ )
+ ) {
+ continue;
+ }
+ }
+ yield {
+ type: 'container',
+ containerType: vectorType,
+ scalarType,
+ };
+ }
+ // Matrices can only be f32.
+ if (scalarType === 'f32') {
+ for (const matrixType of kMatrixContainerTypes) {
+ yield {
+ type: 'container',
+ containerType: matrixType,
+ scalarType,
+ };
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ for (const containerType of ['array', 'struct']) {
+ const innerTypes = generateTypesMemo(depth - 1);
+ switch (containerType) {
+ case 'array':
+ for (const elementCount of kElementCounts[depth]) {
+ for (const innerType of innerTypes) {
+ yield {
+ type: 'container',
+ containerType,
+ elementType: innerType,
+ length: elementCount,
+ };
+ }
+ }
+ break;
+ case 'struct':
+ for (const memberCount of kMemberCounts) {
+ const memberIndices = new Array(memberCount);
+ for (let m = 0; m < memberCount; ++m) {
+ memberIndices[m] = m;
+ }
+
+ // Don't generate all possible combinations of inner struct members,
+ // because that's in the millions. Instead, just round-robin through
+ // to pick member types. Loop through the types, concatenated forward
+ // and backward, three times to produce a bounded but variable set of
+ // types.
+ const memberTypes = [...innerTypes, ...[...innerTypes].reverse()];
+ const seenTypes = new Set();
+ let typeIndex = 0;
+ while (typeIndex < memberTypes.length * 3) {
+ const prevTypeIndex = typeIndex;
+ const members = [];
+ for (const m of memberIndices) {
+ members[m] = memberTypes[typeIndex % memberTypes.length];
+ typeIndex += 1;
+ }
+
+ const t = {
+ type: 'container',
+ containerType,
+ members,
+ };
+ const serializedT = prettyPrint(t);
+ if (seenTypes.has(serializedT)) {
+ // We produced an identical type. shuffle the member indices,
+ // "revert" typeIndex back to where it was before this loop, and
+ // shift it by one. This helps ensure we don't loop forever, and
+ // that we produce a different type on the next iteration.
+ memberIndices.push(memberIndices.shift());
+ typeIndex = prevTypeIndex + 1;
+ continue;
+ }
+ seenTypes.add(serializedT);
+ yield t;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ for (const t of generateTypesMemo(p._containerDepth)) {
+ yield {
+ shaderTypeParam: prettyPrint(t),
+ _type: t,
+ };
+ }
+ })
+ )
+ .batch(15)
+ .fn(async t => {
+ let moduleScope = `
+ struct Output {
+ failed : atomic<u32>
+ }
+ @group(0) @binding(0) var<storage, read_write> output : Output;
+
+ // This uniform value that's a zero is used to prevent the shader compilers from trying to
+ // unroll the massive loops generated by these tests.
+ @group(0) @binding(1) var<uniform> zero : u32;
+ `;
+ let functionScope = '';
+
+ const declaredStructTypes = new Map();
+ const typeDecl = (function ensureType(typeName, type, depth = 0) {
+ switch (type.type) {
+ case 'container':
+ switch (type.containerType) {
+ case 'array':
+ return `array<${ensureType(
+ `${typeName}_ArrayElement`,
+ type.elementType,
+ depth + 1
+ )}, ${type.length}>`;
+ case 'struct': {
+ if (declaredStructTypes.has(type)) {
+ return declaredStructTypes.get(type);
+ }
+
+ const members = type.members
+ .map((member, i) => {
+ return `\n member${i} : ${ensureType(
+ `${typeName}_Member${i}`,
+ member,
+ depth + 1
+ )},`;
+ })
+ .join('');
+ declaredStructTypes.set(type, typeName);
+ moduleScope += `\nstruct ${typeName} {`;
+ moduleScope += members;
+ moduleScope += '\n};';
+
+ return typeName;
+ }
+ default:
+ return `${type.containerType}<${ensureType(
+ typeName,
+ {
+ type: 'scalar',
+ scalarType: type.scalarType,
+ isAtomic: false,
+ },
+ depth + 1
+ )}>`;
+ }
+
+ break;
+ case 'scalar':
+ return type.isAtomic ? `atomic<${type.scalarType}>` : type.scalarType;
+ }
+ })('TestType', t.params._type);
+
+ switch (t.params.storageClass) {
+ case 'workgroup':
+ case 'private':
+ moduleScope += `\nvar<${t.params.storageClass}> testVar: ${typeDecl};`;
+ break;
+ case 'function':
+ functionScope += `\nvar testVar: ${typeDecl};`;
+ break;
+ }
+
+ const checkZeroCode = (function checkZero(value, type, depth = 0) {
+ switch (type.type) {
+ case 'container':
+ switch (type.containerType) {
+ case 'array':
+ return `\nfor (var i${depth} = 0u; i${depth} < ${
+ type.length
+ }u + zero; i${depth} = i${depth} + 1u) {
+ ${checkZero(`${value}[i${depth}]`, type.elementType, depth + 1)}
+ }`;
+ case 'struct':
+ return type.members
+ .map((member, i) => {
+ return checkZero(`${value}.member${i}`, member, depth + 1);
+ })
+ .join('\n');
+ default:
+ if (type.containerType.indexOf('vec') !== -1) {
+ const length = type.containerType[3];
+ return `\nfor (var i${depth} = 0u; i${depth} < ${length}u + zero; i${depth} = i${depth} + 1u) {
+ ${checkZero(
+ `${value}[i${depth}]`,
+ {
+ type: 'scalar',
+ scalarType: type.scalarType,
+ isAtomic: false,
+ },
+ depth + 1
+ )}
+ }`;
+ } else if (type.containerType.indexOf('mat') !== -1) {
+ const cols = type.containerType[3];
+ const rows = type.containerType[5];
+ return `\nfor (var c${depth} = 0u; c${depth} < ${cols}u + zero; c${depth} = c${depth} + 1u) {
+ for (var r${depth} = 0u; r${depth} < ${rows}u; r${depth} = r${depth} + 1u) {
+ ${checkZero(
+ `${value}[c${depth}][r${depth}]`,
+ {
+ type: 'scalar',
+ scalarType: type.scalarType,
+ isAtomic: false,
+ },
+ depth + 1
+ )}
+ }
+ }`;
+ } else {
+ unreachable();
+ }
+ }
+
+ break;
+ case 'scalar': {
+ let expected;
+ switch (type.scalarType) {
+ case 'bool':
+ expected = 'false';
+ break;
+ case 'f32':
+ expected = '0.0';
+ break;
+ case 'i32':
+ expected = '0';
+ break;
+ case 'u32':
+ expected = '0u';
+ break;
+ }
+
+ if (type.isAtomic) {
+ value = `atomicLoad(&${value})`;
+ }
+
+ // Note: this could have an early return, but we omit it because it makes
+ // the tests fail cause with DXGI_ERROR_DEVICE_HUNG on Windows.
+ return `\nif (${value} != ${expected}) { atomicStore(&output.failed, 1u); }`;
+ }
+ }
+ })('testVar', t.params._type);
+
+ const wgsl = `
+ ${moduleScope}
+ @compute @workgroup_size(${t.params.workgroupSize})
+ fn main() {
+ ${functionScope}
+ ${checkZeroCode}
+ _ = zero;
+ }
+ `;
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: wgsl,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const resultBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+ t.trackForCleanup(resultBuffer);
+
+ const zeroBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.UNIFORM,
+ });
+ t.trackForCleanup(zeroBuffer);
+
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: resultBuffer,
+ },
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: zeroBuffer,
+ },
+ },
+ ],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.queue.submit([encoder.finish()]);
+ t.expectGPUBufferValuesEqual(resultBuffer, new Uint32Array([0]));
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js
new file mode 100644
index 0000000000..ef27fe6565
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/types.js
@@ -0,0 +1,193 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { keysOf } from '../../common/util/data_tables.js';
+import { assert } from '../../common/util/util.js';
+import { align } from '../util/math.js';
+
+const kArrayLength = 3;
+
+export const HostSharableTypes = ['i32', 'u32', 'f32'];
+
+/** Info for each plain scalar type. */
+export const kScalarTypeInfo = {
+ i32: { layout: { alignment: 4, size: 4 }, supportsAtomics: true, arrayLength: 1, innerLength: 0 },
+ u32: { layout: { alignment: 4, size: 4 }, supportsAtomics: true, arrayLength: 1, innerLength: 0 },
+ f32: {
+ layout: { alignment: 4, size: 4 },
+ supportsAtomics: false,
+ arrayLength: 1,
+ innerLength: 0,
+ },
+ bool: { layout: undefined, supportsAtomics: false, arrayLength: 1, innerLength: 0 },
+};
+/** List of all plain scalar types. */
+export const kScalarTypes = keysOf(kScalarTypeInfo);
+
+/** Info for each vecN<> container type. */
+export const kVectorContainerTypeInfo = {
+ vec2: { layout: { alignment: 8, size: 8 }, arrayLength: 2, innerLength: 0 },
+ vec3: { layout: { alignment: 16, size: 12 }, arrayLength: 3, innerLength: 0 },
+ vec4: { layout: { alignment: 16, size: 16 }, arrayLength: 4, innerLength: 0 },
+};
+/** List of all vecN<> container types. */
+export const kVectorContainerTypes = keysOf(kVectorContainerTypeInfo);
+
+/** Info for each matNxN<> container type. */
+export const kMatrixContainerTypeInfo = {
+ mat2x2: { layout: { alignment: 8, size: 16 }, arrayLength: 2, innerLength: 2 },
+ mat3x2: { layout: { alignment: 8, size: 24 }, arrayLength: 3, innerLength: 2 },
+ mat4x2: { layout: { alignment: 8, size: 32 }, arrayLength: 4, innerLength: 2 },
+ mat2x3: { layout: { alignment: 16, size: 32 }, arrayLength: 2, innerLength: 3 },
+ mat3x3: { layout: { alignment: 16, size: 48 }, arrayLength: 3, innerLength: 3 },
+ mat4x3: { layout: { alignment: 16, size: 64 }, arrayLength: 4, innerLength: 3 },
+ mat2x4: { layout: { alignment: 16, size: 32 }, arrayLength: 2, innerLength: 4 },
+ mat3x4: { layout: { alignment: 16, size: 48 }, arrayLength: 3, innerLength: 4 },
+ mat4x4: { layout: { alignment: 16, size: 64 }, arrayLength: 4, innerLength: 4 },
+};
+/** List of all matNxN<> container types. */
+export const kMatrixContainerTypes = keysOf(kMatrixContainerTypeInfo);
+
+/** List of texel formats and their shader representation */
+export const TexelFormats = [
+ { format: 'rgba8unorm', _shaderType: 'f32' },
+ { format: 'rgba8snorm', _shaderType: 'f32' },
+ { format: 'rgba8uint', _shaderType: 'u32' },
+ { format: 'rgba8sint', _shaderType: 'i32' },
+ { format: 'rgba16uint', _shaderType: 'u32' },
+ { format: 'rgba16sint', _shaderType: 'i32' },
+ { format: 'rgba16float', _shaderType: 'f32' },
+ { format: 'r32uint', _shaderType: 'u32' },
+ { format: 'r32sint', _shaderType: 'i32' },
+ { format: 'r32float', _shaderType: 'f32' },
+ { format: 'rg32uint', _shaderType: 'u32' },
+ { format: 'rg32sint', _shaderType: 'i32' },
+ { format: 'rg32float', _shaderType: 'f32' },
+ { format: 'rgba32uint', _shaderType: 'i32' },
+ { format: 'rgba32sint', _shaderType: 'i32' },
+ { format: 'rgba32float', _shaderType: 'f32' },
+];
+
+/**
+ * Generate a bunch types (vec, mat, sized/unsized array) for testing.
+ */
+export function* generateTypes({ storageClass, baseType, containerType, isAtomic = false }) {
+ const scalarInfo = kScalarTypeInfo[baseType];
+ if (isAtomic) {
+ assert(scalarInfo.supportsAtomics, 'type does not support atomics');
+ }
+ const scalarType = isAtomic ? `atomic<${baseType}>` : baseType;
+
+ // Storage and uniform require host-sharable types.
+ if (storageClass === 'storage' || storageClass === 'uniform') {
+ assert(isHostSharable(baseType), 'type ' + baseType.toString() + ' is not host sharable');
+ }
+
+ // Scalar types
+ if (containerType === 'scalar') {
+ yield {
+ type: `${scalarType}`,
+ _kTypeInfo: {
+ elementBaseType: `${scalarType}`,
+ ...scalarInfo,
+ },
+ };
+ }
+
+ // Vector types
+ if (containerType === 'vector') {
+ for (const vectorType of kVectorContainerTypes) {
+ yield {
+ type: `${vectorType}<${scalarType}>`,
+ _kTypeInfo: { elementBaseType: baseType, ...kVectorContainerTypeInfo[vectorType] },
+ };
+ }
+ }
+
+ if (containerType === 'matrix') {
+ // Matrices can only be f32.
+ if (baseType === 'f32') {
+ for (const matrixType of kMatrixContainerTypes) {
+ const matrixInfo = kMatrixContainerTypeInfo[matrixType];
+ yield {
+ type: `${matrixType}<${scalarType}>`,
+ _kTypeInfo: {
+ elementBaseType: `vec${matrixInfo.innerLength}<${scalarType}>`,
+ ...matrixInfo,
+ },
+ };
+ }
+ }
+ }
+
+ // Array types
+ if (containerType === 'array') {
+ const arrayTypeInfo = {
+ elementBaseType: `${baseType}`,
+ arrayLength: kArrayLength,
+ layout: scalarInfo.layout
+ ? {
+ alignment: scalarInfo.layout.alignment,
+ size:
+ storageClass === 'uniform'
+ ? // Uniform storage class must have array elements aligned to 16.
+ kArrayLength *
+ arrayStride({
+ ...scalarInfo.layout,
+ alignment: 16,
+ })
+ : kArrayLength * arrayStride(scalarInfo.layout),
+ }
+ : undefined,
+ };
+
+ // Sized
+ if (storageClass === 'uniform') {
+ yield {
+ type: `array<vec4<${scalarType}>,${kArrayLength}>`,
+ _kTypeInfo: arrayTypeInfo,
+ };
+ } else {
+ yield { type: `array<${scalarType},${kArrayLength}>`, _kTypeInfo: arrayTypeInfo };
+ }
+ // Unsized
+ if (storageClass === 'storage') {
+ yield { type: `array<${scalarType}>`, _kTypeInfo: arrayTypeInfo };
+ }
+ }
+
+ function arrayStride(elementLayout) {
+ return align(elementLayout.size, elementLayout.alignment);
+ }
+
+ function isHostSharable(baseType) {
+ for (const sharableType of HostSharableTypes) {
+ if (sharableType === baseType) return true;
+ }
+ return false;
+ }
+}
+
+/** Atomic access requires scalar/array container type and storage/workgroup memory. */
+export function supportsAtomics(p) {
+ return (
+ ((p.storageClass === 'storage' && p.storageMode === 'read_write') ||
+ p.storageClass === 'workgroup') &&
+ (p.containerType === 'scalar' || p.containerType === 'array')
+ );
+}
+
+/** Generates an iterator of supported base types (i32/u32/f32/bool) */
+export function* supportedScalarTypes(p) {
+ for (const scalarType of kScalarTypes) {
+ const info = kScalarTypeInfo[scalarType];
+
+ // Test atomics only on supported scalar types.
+ if (p.isAtomic && !info.supportsAtomics) continue;
+
+ // Storage and uniform require host-sharable types.
+ const isHostShared = p.storageClass === 'storage' || p.storageClass === 'uniform';
+ if (isHostShared && info.layout === undefined) continue;
+
+ yield scalarType;
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/align.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/align.spec.js
new file mode 100644
index 0000000000..05d690d0b6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/align.spec.js
@@ -0,0 +1,182 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for @align`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kValidAlign = new Set([
+ '',
+ '@align(1)',
+ '@align(4)',
+ '@align(4i)',
+ '@align(4u)',
+ '@align(0x4)',
+ '@align(4,)',
+ '@align(u_val)',
+ '@align(i_val)',
+ '@align(i_val + 4 - 6)',
+ '@align(1073741824)',
+ '@\talign\t(4)',
+ '@/^comment^/align/^comment^/(4)',
+]);
+
+const kInvalidAlign = new Set([
+ '@malign(4)',
+ '@align()',
+ '@align 4)',
+ '@align(4',
+ '@align(4, 2)',
+ '@align(4,)',
+ '@align(3)', // Not a power of 2
+ '@align(f_val)',
+ '@align(1.0)',
+ '@align(4f)',
+ '@align(4h)',
+ '@align',
+ '@align(0)',
+ '@align(-4)',
+ '@align(2147483646)', // Not a power of 2
+ '@align(2147483648)', // Larger then max i32
+]);
+
+g.test('align_parsing')
+ .desc(`Test that @align is parsed correctly.`)
+ .params(u => u.combine('align', new Set([...kValidAlign, ...kInvalidAlign])))
+ .fn(t => {
+ const v = t.params.align.replace(/\^/g, '*');
+ const code = `
+const i_val: i32 = 4;
+const u_val: u32 = 4;
+const f_val: f32 = 4.2;
+struct B {
+ ${v} a: i32,
+}
+
+@group(0) @binding(0)
+var<uniform> uniform_buffer: B;
+
+@fragment
+fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(.4, .2, .3, .1);
+}`;
+ t.expectCompileResult(kValidAlign.has(t.params.align), code);
+ });
+
+g.test('align_required_alignment')
+ .desc('Test that the align with an invalid size is an error')
+ .params(u =>
+ u
+ .combine('address_space', ['storage', 'uniform'])
+ // These test a few cases:
+ // * 1 -- Invalid, alignment smaller then all the required alignments
+ // * alignment -- Valid, the required alignment
+ // * 32 -- Valid, an alignment larger then the required alignment.
+ .combine('align', [1, 2, 'alignment', 32])
+ .combine('type', [
+ { name: 'i32', storage: 4, uniform: 4 },
+ { name: 'u32', storage: 4, uniform: 4 },
+ { name: 'f32', storage: 4, uniform: 4 },
+ { name: 'f16', storage: 2, uniform: 2 },
+ { name: 'atomic<i32>', storage: 4, uniform: 4 },
+ { name: 'vec2<i32>', storage: 8, uniform: 8 },
+ { name: 'vec2<f16>', storage: 4, uniform: 4 },
+ { name: 'vec3<u32>', storage: 16, uniform: 16 },
+ { name: 'vec3<f16>', storage: 8, uniform: 8 },
+ { name: 'vec4<f32>', storage: 16, uniform: 16 },
+ { name: 'vec4<f16>', storage: 8, uniform: 8 },
+ { name: 'mat2x2<f32>', storage: 8, uniform: 8 },
+ { name: 'mat3x2<f32>', storage: 8, uniform: 8 },
+ { name: 'mat4x2<f32>', storage: 8, uniform: 8 },
+ { name: 'mat2x2<f16>', storage: 4, uniform: 4 },
+ { name: 'mat3x2<f16>', storage: 4, uniform: 4 },
+ { name: 'mat4x2<f16>', storage: 4, uniform: 4 },
+ { name: 'mat2x3<f32>', storage: 16, uniform: 16 },
+ { name: 'mat3x3<f32>', storage: 16, uniform: 16 },
+ { name: 'mat4x3<f32>', storage: 16, uniform: 16 },
+ { name: 'mat2x3<f16>', storage: 8, uniform: 8 },
+ { name: 'mat3x3<f16>', storage: 8, uniform: 8 },
+ { name: 'mat4x3<f16>', storage: 8, uniform: 8 },
+ { name: 'mat2x4<f32>', storage: 16, uniform: 16 },
+ { name: 'mat3x4<f32>', storage: 16, uniform: 16 },
+ { name: 'mat4x4<f32>', storage: 16, uniform: 16 },
+ { name: 'mat2x4<f16>', storage: 8, uniform: 8 },
+ { name: 'mat3x4<f16>', storage: 8, uniform: 8 },
+ { name: 'mat4x4<f16>', storage: 8, uniform: 8 },
+ { name: 'array<vec2<i32>, 2>', storage: 8, uniform: 16 },
+ { name: 'array<vec4<i32>, 2>', storage: 8, uniform: 16 },
+ { name: 'S', storage: 8, uniform: 16 },
+ ])
+ .beginSubcases()
+ )
+ .beforeAllSubcases(t => {
+ if (t.params.type.name.includes('f16')) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ // While this would fail validation, it doesn't fail for any reasons related to alignment.
+ // Atomics are not allowed in uniform address space as they have to be read_write.
+ if (t.params.address_space === 'uniform' && t.params.type.name.startsWith('atomic')) {
+ t.skip('No atomics in uniform address space');
+ }
+
+ let code = '';
+ if (t.params.type.name.includes('f16')) {
+ code += 'enable f16;\n';
+ }
+
+ // Testing the struct case, generate the structf
+ if (t.params.type.name === 'S') {
+ code += `struct S {
+ a: mat4x2<f32>, // Align 8
+ b: array<vec${
+ t.params.address_space === 'storage' ? 2 : 4
+ }<i32>, 2>, // Storage align 8, uniform 16
+ }
+ `;
+ }
+
+ let align = t.params.align;
+ if (t.params.align === 'alignment') {
+ // Alignment value listed in the spec
+ if (t.params.address_space === 'storage') {
+ align = `${t.params.type.storage}`;
+ } else {
+ align = `${t.params.type.uniform}`;
+ }
+ }
+
+ let address_space = 'uniform';
+ if (t.params.address_space === 'storage') {
+ // atomics require read_write, not just the default of read
+ address_space = 'storage, read_write';
+ }
+
+ code += `struct MyStruct {
+ @align(${align}) a: ${t.params.type.name},
+ }
+
+ @group(0) @binding(0)
+ var<${address_space}> a : MyStruct;`;
+
+ code += `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(.4, .2, .3, .1);
+ }`;
+
+ const fails =
+ // An alignment of 1 is never valid as it is smaller then all required alignments.
+ t.params.align === 1 ||
+ // Except for f16, 2 should also fail as being too small.
+ (t.params.align === 2 && t.params.type.name !== 'f16') ||
+ // An array of `vec2` in uniform will not validate because, while the alignment on the array
+ // itself is fine, the `vec2` element inside the array will have the wrong alignment. Uniform
+ // requires that inner vec2 to have an align 16 which can only be done by specifying `vec4`
+ // instead.
+ (t.params.address_space === 'uniform' && t.params.type.name.startsWith('array<vec2'));
+
+ t.expectCompileResult(!fails, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/blankspace.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/blankspace.spec.js
new file mode 100644
index 0000000000..3013ad37a0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/blankspace.spec.js
@@ -0,0 +1,51 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for blankspace handling`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('null_characters')
+ .desc(`Test that WGSL source containing a null character is rejected.`)
+ .params(u =>
+ u
+ .combine('contains_null', [true, false])
+ .combine('placement', ['comment', 'delimiter', 'eol'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ let code = '';
+ if (t.params.placement === 'comment') {
+ code = `// Here is a ${t.params.contains_null ? '\0' : 'Z'} character`;
+ } else if (t.params.placement === 'delimiter') {
+ code = `const${t.params.contains_null ? '\0' : ' '}name : i32 = 0;`;
+ } else if (t.params.placement === 'eol') {
+ code = `const name : i32 = 0;${t.params.contains_null ? '\0' : ''}`;
+ }
+ t.expectCompileResult(!t.params.contains_null, code);
+ });
+
+g.test('blankspace')
+ .desc(`Test that all blankspace characters act as delimiters.`)
+ .params(u =>
+ u
+ .combine('blankspace', [
+ ['\u0020', 'space'],
+ ['\u0009', 'horizontal_tab'],
+ ['\u000a', 'line_feed'],
+ ['\u000b', 'vertical_tab'],
+ ['\u000c', 'form_feed'],
+ ['\u000d', 'carriage_return'],
+ ['\u0085', 'next_line'],
+ ['\u200e', 'left_to_right_mark'],
+ ['\u200f', 'right_to_left_mark'],
+ ['\u2028', 'line_separator'],
+ ['\u2029', 'paragraph_separator'],
+ ])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const code = `const${t.params.blankspace[0]}ident : i32 = 0;`;
+ t.expectCompileResult(true, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/builtin.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/builtin.spec.js
new file mode 100644
index 0000000000..7c678531e1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/builtin.spec.js
@@ -0,0 +1,39 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for @builtin`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kValidBuiltin = new Set([
+ `@builtin(position)`,
+ `@builtin(position,)`,
+ `@ \n builtin(position)`,
+ `@/^ comment ^/builtin/^ comment ^/\n\n(\t/^comment^/position/^comment^/)`,
+]);
+
+const kInvalidBuiltin = new Set([
+ `@abuiltin(position)`,
+ `@builtin`,
+ `@builtin()`,
+ `@builtin position`,
+ `@builtin position)`,
+ `@builtin(position`,
+ `@builtin(position, frag_depth)`,
+ `@builtin(identifier)`,
+ `@builtin(2)`,
+]);
+
+g.test('parse')
+ .desc(`Test that @builtin is parsed correctly.`)
+ .params(u => u.combine('builtin', new Set([...kValidBuiltin, ...kInvalidBuiltin])))
+ .fn(t => {
+ const v = t.params.builtin.replace(/\^/g, '*');
+ const code = `
+@vertex
+fn main() -> ${v} vec4<f32> {
+ return vec4<f32>(.4, .2, .3, .1);
+}`;
+ t.expectCompileResult(kValidBuiltin.has(t.params.builtin), code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/comments.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/comments.spec.js
new file mode 100644
index 0000000000..748e70bb2a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/comments.spec.js
@@ -0,0 +1,76 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for comments`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('comments')
+ .desc(`Test that valid comments are handled correctly, including nesting.`)
+ .fn(t => {
+ const code = `
+/**
+ * Here is my shader.
+ *
+ * /* I can nest /**/ comments. */
+ * // I can nest line comments too.
+ **/
+@fragment // This is the stage
+fn main(/*
+no
+parameters
+*/) -> @location(0) vec4<f32> {
+ return/*block_comments_delimit_tokens*/vec4<f32>(.4, .2, .3, .1);
+}/* terminated block comments are OK at EOF...*/`;
+ t.expectCompileResult(true, code);
+ });
+
+g.test('line_comment_eof')
+ .desc(`Test that line comments can come at EOF.`)
+ .fn(t => {
+ const code = `
+@fragment
+fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(.4, .2, .3, .1);
+}
+// line comments are OK at EOF...`;
+ t.expectCompileResult(true, code);
+ });
+
+g.test('line_comment_terminators')
+ .desc(`Test that line comments are terminated by any blankspace other than space and \t`)
+ .params(u =>
+ u
+ .combine('blankspace', [
+ [' ', 'space'],
+ ['\t', 'tab'],
+ ['\u000a', 'line_feed'],
+ ['\u000b', 'vertical_tab'],
+ ['\u000c', 'form_feed'],
+ ['\u000d', 'carriage_return'],
+ ['\u000d\u000a', 'carriage_return_line_feed'],
+ ['\u0085', 'next_line'],
+ ['\u2028', 'line_separator'],
+ ['\u2029', 'paragraph_separator'],
+ ])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const code = `// Line comment${t.params.blankspace[0]}const invalid_outside_comment = should_fail`;
+
+ t.expectCompileResult([' ', '\t'].includes(t.params.blankspace[0]), code);
+ });
+
+g.test('unterminated_block_comment')
+ .desc(`Test that unterminated block comments cause an error`)
+ .params(u => u.combine('terminated', [true, false]).beginSubcases())
+ .fn(t => {
+ const code = `
+/**
+ * Unterminated block comment.
+ *
+ ${t.params.terminated ? '*/' : ''}`;
+
+ t.expectCompileResult(t.params.terminated, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/identifiers.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/identifiers.spec.js
new file mode 100644
index 0000000000..e66e7abb42
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/identifiers.spec.js
@@ -0,0 +1,280 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for identifiers`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kValidIdentifiers = new Set([
+ 'foo',
+ 'Foo',
+ 'FOO',
+ '_0',
+ '_foo0',
+ '_0foo',
+ 'foo__0',
+ 'Δέλτα',
+ 'réflexion',
+ 'Кызыл',
+ '𐰓𐰏𐰇',
+ '朝焼け',
+ 'سلام',
+ '검정',
+ 'שָׁלוֹם',
+ 'गुलाबी',
+ 'փիրուզ',
+]);
+
+const kInvalidIdentifiers = new Set([
+ '_', // Single underscore is a syntactic token for phony assignment.
+ '__', // Leading double underscore is reserved.
+ '__foo', // Leading double underscore is reserved.
+ '0foo', // Must start with single underscore or a letter.
+ // No punctuation:
+ 'foo.bar',
+ 'foo-bar',
+ 'foo+bar',
+ 'foo#bar',
+ 'foo!bar',
+ 'foo\\bar',
+ 'foo/bar',
+ 'foo,bar',
+ 'foo@bar',
+ 'foo::bar',
+ // Type-defining Keywords:
+ 'array',
+ 'atomic',
+ 'bool',
+ 'f32',
+ 'f16',
+ 'i32',
+ 'mat2x2',
+ 'mat2x3',
+ 'mat2x4',
+ 'mat3x2',
+ 'mat3x3',
+ 'mat3x4',
+ 'mat4x2',
+ 'mat4x3',
+ 'mat4x4',
+ 'ptr',
+ 'sampler',
+ 'sampler_comparison',
+ 'texture_1d',
+ 'texture_2d',
+ 'texture_2d_array',
+ 'texture_3d',
+ 'texture_cube',
+ 'texture_cube_array',
+ 'texture_multisampled_2d',
+ 'texture_storage_1d',
+ 'texture_storage_2d',
+ 'texture_storage_2d_array',
+ 'texture_storage_3d',
+ 'texture_depth_2d',
+ 'texture_depth_2d_array',
+ 'texture_depth_cube',
+ 'texture_depth_cube_array',
+ 'texture_depth_multisampled_2d',
+ 'u32',
+ 'vec2',
+ 'vec3',
+ 'vec4',
+ // Other Keywords:
+ 'bitcast',
+ 'break',
+ 'case',
+ 'const',
+ 'continue',
+ 'continuing',
+ 'default',
+ 'discard',
+ 'else',
+ 'enable',
+ 'false',
+ 'fn',
+ 'for',
+ 'if',
+ 'let',
+ 'loop',
+ 'override',
+ 'return',
+ 'static_assert',
+ 'struct',
+ 'switch',
+ 'true',
+ 'type',
+ 'var',
+ 'while',
+ // Reserved Words
+ 'CompileShader',
+ 'ComputeShader',
+ 'DomainShader',
+ 'GeometryShader',
+ 'Hullshader',
+ 'NULL',
+ 'Self',
+ 'abstract',
+ 'active',
+ 'alignas',
+ 'alignof',
+ 'as',
+ 'asm',
+ 'asm_fragment',
+ 'async',
+ 'attribute',
+ 'auto',
+ 'await',
+ 'become',
+ 'binding_array',
+ 'cast',
+ 'catch',
+ 'class',
+ 'co_await',
+ 'co_return',
+ 'co_yield',
+ 'coherent',
+ 'column_major',
+ 'common',
+ 'compile',
+ 'compile_fragment',
+ 'concept',
+ 'const_cast',
+ 'consteval',
+ 'constexpr',
+ 'constinit',
+ 'crate',
+ 'debugger',
+ 'decltype',
+ 'delete',
+ 'demote',
+ 'demote_to_helper',
+ 'do',
+ 'dynamic_cast',
+ 'enum',
+ 'explicit',
+ 'export',
+ 'extends',
+ 'extern',
+ 'external',
+ 'fallthrough',
+ 'filter',
+ 'final',
+ 'finally',
+ 'friend',
+ 'from',
+ 'fxgroup',
+ 'get',
+ 'goto',
+ 'groupshared',
+ 'handle',
+ 'highp',
+ 'impl',
+ 'implements',
+ 'import',
+ 'inline',
+ 'inout',
+ 'instanceof',
+ 'interface',
+ 'layout',
+ 'lowp',
+ 'macro',
+ 'macro_rules',
+ 'match',
+ 'mediump',
+ 'meta',
+ 'mod',
+ 'module',
+ 'move',
+ 'mut',
+ 'mutable',
+ 'namespace',
+ 'new',
+ 'nil',
+ 'noexcept',
+ 'noinline',
+ 'nointerpolation',
+ 'noperspective',
+ 'null',
+ 'nullptr',
+ 'of',
+ 'operator',
+ 'package',
+ 'packoffset',
+ 'partition',
+ 'pass',
+ 'patch',
+ 'pixelfragment',
+ 'precise',
+ 'precision',
+ 'premerge',
+ 'priv',
+ 'protected',
+ 'pub',
+ 'public',
+ 'readonly',
+ 'ref',
+ 'regardless',
+ 'register',
+ 'reinterpret_cast',
+ 'requires',
+ 'resource',
+ 'restrict',
+ 'self',
+ 'set',
+ 'shared',
+ 'signed',
+ 'sizeof',
+ 'smooth',
+ 'snorm',
+ 'static',
+ 'static_cast',
+ 'std',
+ 'subroutine',
+ 'super',
+ 'target',
+ 'template',
+ 'this',
+ 'thread_local',
+ 'throw',
+ 'trait',
+ 'try',
+ 'typedef',
+ 'typeid',
+ 'typename',
+ 'typeof',
+ 'union',
+ 'unless',
+ 'unorm',
+ 'unsafe',
+ 'unsized',
+ 'use',
+ 'using',
+ 'varying',
+ 'virtual',
+ 'volatile',
+ 'wgsl',
+ 'where',
+ 'with',
+ 'writeonly',
+ 'yield',
+]);
+
+g.test('identifiers')
+ .desc(`Test that valid identifiers are accepted, and invalid identifiers are rejected.`)
+ .params(u =>
+ u.combine('ident', new Set([...kValidIdentifiers, ...kInvalidIdentifiers])).beginSubcases()
+ )
+ .fn(t => {
+ const code = `var<private> ${t.params.ident} : i32;`;
+ t.expectCompileResult(kValidIdentifiers.has(t.params.ident), code);
+ });
+
+g.test('non_normalized')
+ .desc(`Test that identifiers are not unicode normalized`)
+ .fn(t => {
+ const code = `var<private> \u212b : i32; // \u212b normalizes with NFC to \u00c5
+var<private> \u00c5 : i32;`;
+ t.expectCompileResult(true, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/literal.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/literal.spec.js
new file mode 100644
index 0000000000..a1ca97984e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/literal.spec.js
@@ -0,0 +1,298 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for literals`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('bools')
+ .desc(`Test that valid bools are accepted.`)
+ .params(u => u.combine('val', ['true', 'false']).beginSubcases())
+ .fn(t => {
+ const code = `var test = ${t.params.val};`;
+ t.expectCompileResult(true, t.wrapInEntryPoint(code));
+ });
+
+const kAbstractIntNonNegative = new Set([
+ '0x123', // hex number
+ '123', // signed number, no suffix
+ '0', // zero
+ '0x3f', // hex with 'f' as last character
+ '2147483647', // max signed int
+]);
+
+const kAbstractIntNegative = new Set([
+ '-0x123', // hex number
+ '-123', // signed number, no suffix
+ '-0x3f', // hex with 'f' as last character
+ '-2147483647', // nagative of max signed int
+ '-2147483648', // min signed int
+]);
+
+const kI32 = new Set([
+ '94i', // signed number
+ '2147483647i', // max signed int
+ '-2147483647i', // min parsable signed int
+ 'i32(-2147483648)', // min signed int
+]);
+
+const kU32 = new Set([
+ '42u', // unsigned number
+ '0u', // min unsigned int
+ '4294967295u', // max unsigned int
+]);
+
+{
+ const kValidIntegers = new Set([
+ ...kAbstractIntNonNegative,
+ ...kAbstractIntNegative,
+ ...kI32,
+ ...kU32,
+ ]);
+
+ const kInvalidIntegers = new Set([
+ '0123', // Integer does not start with zero
+ '2147483648i', // max signed int + 1
+ '-2147483649i', // min signed int - 1
+ '4294967295', // a untyped lhs will be i32, so this is too big
+ '4294967295i', // max unsigned int with i suffix
+ '4294967296u', // max unsigned int + 1
+ '-1u', // negative unsigned
+ ]);
+ g.test('abstract_int')
+ .desc(`Test that valid integers are accepted, and invalid integers are rejected.`)
+ .params(u =>
+ u.combine('val', new Set([...kValidIntegers, ...kInvalidIntegers])).beginSubcases()
+ )
+ .fn(t => {
+ const code = `var test = ${t.params.val};`;
+ t.expectCompileResult(kValidIntegers.has(t.params.val), t.wrapInEntryPoint(code));
+ });
+}
+
+{
+ const kValidI32 = new Set([...kAbstractIntNonNegative, ...kAbstractIntNegative, ...kI32]);
+ const kInvalidI32 = new Set([
+ ...kU32,
+ '2147483648', // max signed int + 1
+ '2147483648i', // max signed int + 1
+ '-2147483649', // min signed int - 1
+ '-2147483649i', // min signed int - 1
+ '1.0', // no conversion from float
+ '1.0f', // no conversion from float
+ '1.0h', // no conversion from float
+ ]);
+ g.test('i32')
+ .desc(`Test that valid signed integers are accepted, and invalid signed integers are rejected.`)
+ .params(u => u.combine('val', new Set([...kValidI32, ...kInvalidI32])).beginSubcases())
+ .beforeAllSubcases(t => {
+ if (t.params.val.includes('h')) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ const { val } = t.params;
+ const code = `var test: i32 = ${val};`;
+ const extensionList = val.includes('h') ? ['f16'] : [];
+ t.expectCompileResult(kValidI32.has(val), t.wrapInEntryPoint(code, extensionList));
+ });
+}
+
+{
+ const kValidU32 = new Set([
+ ...kAbstractIntNonNegative,
+ ...kU32,
+ '4294967295', // max unsigned
+ ]);
+ const kInvalidU32 = new Set([
+ ...kAbstractIntNegative,
+ ...kI32,
+ '4294967296', // max unsigned int + 1
+ '4294967296u', // min unsigned int + 1
+ '-1', // min unsigned int - 1
+ '1.0', // no conversion from float
+ '1.0f', // no conversion from float
+ '1.0h', // no conversion from float
+ ]);
+ g.test('u32')
+ .desc(
+ `Test that valid unsigned integers are accepted, and invalid unsigned integers are rejected.`
+ )
+ .params(u => u.combine('val', new Set([...kValidU32, ...kInvalidU32])).beginSubcases())
+ .beforeAllSubcases(t => {
+ if (t.params.val.includes('h')) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ const { val } = t.params;
+ const code = `var test: u32 = ${val};`;
+ const extensionList = val.includes('h') ? ['f16'] : [];
+ t.expectCompileResult(kValidU32.has(val), t.wrapInEntryPoint(code, extensionList));
+ });
+}
+
+const kF32 = new Set([
+ '0f', // Zero float
+ '0.0f', // Zero float
+ '12.223f', // float value
+ '12.f', // .f
+ '.12f', // No leading number with a f
+ '2.4e+4f', // Positive exponent with f suffix
+ '2.4e-2f', // Negative exponent with f suffix
+ '2.e+4f', // Exponent without decimals
+ '1e-4f', // Exponennt without decimal point
+ '0x1P+4f', // Hex float no decimal
+]);
+
+const kF16 = new Set([
+ '0h', // Zero half
+ '1h', // Half no decimal
+ '.1h', // Half no leading value
+ '1.1e2h', // Exponent half no sign
+ '1.1E+2h', // Exponent half, plus (uppercase E)
+ '2.4e-2h', // Exponent half, negative
+ '0xep2h', // Hexfloat half lower case p
+ '0xEp-2h', // Hexfloat uppcase hex value
+ '0x3p+2h', // Hex float half positive exponent
+ '0x3.2p+2h', // Hex float with decimal half
+]);
+
+const kAbstractFloat = new Set([
+ '0.0', // Zero float without suffix
+ '.0', // Zero float without leading value
+ '12.', // No decimal points
+ '00012.', // Leading zeros allowed
+ '.12', // No leading digits
+ '1.2e2', // Exponent without sign (lowercase e)
+ '1.2E2', // Exponent without sign (uppercase e)
+ '1.2e+2', // positive exponent
+ '2.4e-2', // Negative exponent
+ '.1e-2', // Exponent without leading number
+ '0x.3', // Hex float, lowercase X
+ '0X.3', // Hex float, uppercase X
+ '0xa.fp+2', // Hex float, lowercase p
+ '0xa.fP+2', // Hex float, uppercase p
+ '0xE.fp+2', // Uppercase E (as hex, but matches non hex exponent char)
+ '0X1.fp-4', // Hex float negative exponent
+]);
+
+{
+ const kValidFloats = new Set([...kF32, ...kF16, ...kAbstractFloat]);
+ const kInvalidFloats = new Set([
+ '.f', // Must have a number
+ '.e-2', // Exponent without leading values
+ '1.e&2f', // Exponent invalid sign
+ '1.ef', // Exponent without value
+ '1.e+f', // Exponent sign no value
+ '0x.p2', // Hex float no value
+ '0x1p', // Hex float missing exponent
+ '0x1p^', // Hex float invalid exponent
+ '1.0e+999999999999f', // Too big
+ '0x1.0p+999999999999f', // Too big hex
+ '0x1.00000001pf0', // Mantissa too big
+ ]);
+ const kInvalidF16s = new Set([
+ '1.1eh', // Missing exponent value
+ '1.1e%2h', // Invalid exponent sign
+ '1.1e+h', // Missing exponent with sign
+ '1.0e+999999h', // Too large
+ '0x1.0p+999999h', // Too large hex
+ '0xf.h', // Having suffix "h" without "p" or "P"
+ '0x3h', // Having suffix "h" without "p" or "P"
+ ]);
+
+ g.test('abstract_float')
+ .desc(`Test that valid floats are accepted, and invalid floats are rejected`)
+ .params(u =>
+ u
+ .combine('val', new Set([...kValidFloats, ...kInvalidFloats, ...kInvalidF16s]))
+ .beginSubcases()
+ )
+ .beforeAllSubcases(t => {
+ if (kF16.has(t.params.val) || kInvalidF16s.has(t.params.val)) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ const code = `var test = ${t.params.val};`;
+ const extensionList = kF16.has(t.params.val) || kInvalidF16s.has(t.params.val) ? ['f16'] : [];
+ t.expectCompileResult(
+ kValidFloats.has(t.params.val),
+ t.wrapInEntryPoint(code, extensionList)
+ );
+ });
+}
+
+{
+ const kValidF32 = new Set([
+ ...kF32,
+ ...kAbstractFloat,
+ '1', // AbstractInt
+ '-1', // AbstractInt
+ ]);
+ const kInvalidF32 = new Set([
+ ...kF16, // no conversion
+ '1u', // unsigned
+ '1i', // signed
+ '1h', // half float
+ '.f', // Must have a number
+ '.e-2', // Exponent without leading values
+ '1.e&2f', // Exponent invalid sign
+ '1.ef', // Exponent without value
+ '1.e+f', // Exponent sign no value
+ '0x.p2', // Hex float no value
+ '0x1p', // Hex float missing exponent
+ '0x1p^', // Hex float invalid exponent
+ '1.0e+999999999999f', // Too big
+ '0x1.0p+999999999999f', // Too big hex
+ '0x1.00000001pf0', // Mantissa too big
+ ]);
+
+ g.test('f32')
+ .desc(`Test that valid floats are accepted, and invalid floats are rejected`)
+ .params(u => u.combine('val', new Set([...kValidF32, ...kInvalidF32])).beginSubcases())
+ .beforeAllSubcases(t => {
+ if (kF16.has(t.params.val)) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ const { val } = t.params;
+ const code = `var test: f32 = ${val};`;
+ const extensionList = kF16.has(val) ? ['f16'] : [];
+ t.expectCompileResult(kValidF32.has(val), t.wrapInEntryPoint(code, extensionList));
+ });
+}
+
+{
+ const kValidF16 = new Set([
+ ...kF16,
+ ...kAbstractFloat,
+ '1', // AbstractInt
+ '-1', // AbstractInt
+ ]);
+ const kInvalidF16 = new Set([
+ ...kF32,
+ '1i', // signed int
+ '1u', // unsigned int
+ '1f', // no conversion from f32 to f16
+ '1.1eh', // Missing exponent value
+ '1.1e%2h', // Invalid exponent sign
+ '1.1e+h', // Missing exponent with sign
+ '1.0e+999999h', // Too large
+ '0x1.0p+999999h', // Too large hex
+ ]);
+
+ g.test('f16')
+ .desc(
+ `
+Test that valid half floats are accepted, and invalid half floats are rejected
+
+TODO: Need to inject the 'enable fp16' into the shader to enable the parsing.
+`
+ )
+ .params(u => u.combine('val', new Set([...kValidF16, ...kInvalidF16])).beginSubcases())
+ .unimplemented();
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js
new file mode 100644
index 0000000000..3e32944581
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/semicolon.spec.js
@@ -0,0 +1,270 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for semicolon placements`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('module_scope_single')
+ .desc(`Test that a semicolon can be placed at module scope.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `;`);
+ });
+
+g.test('module_scope_multiple')
+ .desc(`Test that multiple semicolons can be placed at module scope.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `;;;`);
+ });
+
+g.test('after_enable')
+ .desc(`Test that a semicolon must be placed after an enable directive.`)
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
+ })
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `enable f16;`);
+ t.expectCompileResult(/* pass */ false, `enable f16`);
+ });
+
+g.test('after_struct_decl')
+ .desc(`Test that a semicolon can be placed after an struct declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `struct S { x : i32 };`);
+ t.expectCompileResult(/* pass */ true, `struct S { x : i32 }`);
+ });
+
+g.test('after_member')
+ .desc(`Test that a semicolon must not be placed after an struct member declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `struct S { x : i32 }`);
+ t.expectCompileResult(/* pass */ false, `struct S { x : i32; }`);
+ });
+
+g.test('after_func_decl')
+ .desc(`Test that a semicolon can be placed after a function declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() {};`);
+ t.expectCompileResult(/* pass */ true, `fn f() {}`);
+ });
+
+g.test('after_type_alias_decl')
+ .desc(`Test that a semicolon must be placed after an type alias declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `type T = i32;`);
+ t.expectCompileResult(/* pass */ false, `type T = i32`);
+ });
+
+g.test('after_return')
+ .desc(`Test that a semicolon must be placed after a return statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { return; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { return }`);
+ });
+
+g.test('after_call')
+ .desc(`Test that a semicolon must be placed after a function call.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { workgroupBarrier(); }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { workgroupBarrier() }`);
+ });
+
+g.test('after_module_const_decl')
+ .desc(`Test that a semicolon must be placed after a module-scope const declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `const v = 1;`);
+ t.expectCompileResult(/* pass */ false, `const v = 1`);
+ });
+
+g.test('after_fn_const_decl')
+ .desc(`Test that a semicolon must be placed after a function-scope const declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { const v = 1; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { const v = 1 }`);
+ });
+
+g.test('after_module_var_decl')
+ .desc(`Test that a semicolon must be placed after a module-scope var declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `var<private> v = 1;`);
+ t.expectCompileResult(/* pass */ false, `var<private> v = 1`);
+ });
+
+g.test('after_fn_var_decl')
+ .desc(`Test that a semicolon must be placed after a function-scope var declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { var v = 1; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { var v = 1 }`);
+ });
+
+g.test('after_let_decl')
+ .desc(`Test that a semicolon must be placed after a let declaration.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { let v = 1; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { let v = 1 }`);
+ });
+
+g.test('after_discard')
+ .desc(`Test that a semicolon must be placed after a discard statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { discard; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { discard }`);
+ });
+
+g.test('after_assignment')
+ .desc(`Test that a semicolon must be placed after an assignment statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { var v = 1; v = 2; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { var v = 1; v = 2 }`);
+ });
+
+g.test('after_fn_static_assert')
+ .desc(`Test that a semicolon must be placed after an function-scope static assert.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { static_assert(true); }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { static_assert(true) }`);
+ });
+
+g.test('function_body_single')
+ .desc(`Test that a semicolon can be placed in a function body.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { ; }`);
+ });
+
+g.test('function_body_multiple')
+ .desc(`Test that multiple semicolons can be placed in a function body.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { ;;; }`);
+ });
+
+g.test('compound_statement_single')
+ .desc(`Test that a semicolon can be placed in a compound statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { { ; } }`);
+ });
+
+g.test('compound_statement_multiple')
+ .desc(`Test that multiple semicolons can be placed in a compound statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { { ;;; } }`);
+ });
+
+g.test('after_compound_statement')
+ .desc(`Test that a semicolon can be placed after a compound statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { {} ; }`);
+ });
+
+g.test('after_if')
+ .desc(`Test that a semicolon can be placed after an if-statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { if true {} ; }`);
+ });
+
+g.test('after_if_else')
+ .desc(`Test that a semicolon can be placed after an if-else-statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { if true {} else {} ; }`);
+ });
+
+g.test('after_switch')
+ .desc(`Test that a semicolon can be placed after an switch-statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { switch 1 { default {} } ; }`);
+ });
+
+g.test('after_case')
+ .desc(`Test that a semicolon cannot be placed after a non-default switch case.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ false, `fn f() { switch 1 { case 1 {}; default {} } }`);
+ t.expectCompileResult(/* pass */ true, `fn f() { switch 1 { case 1 {} default {} } }`);
+ });
+
+g.test('after_case_break')
+ .desc(`Test that a semicolon must be placed after a case break statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ false, `fn f() { switch 1 { case 1 { break } default {} } }`);
+ t.expectCompileResult(/* pass */ true, `fn f() { switch 1 { case 1 { break; } default {} } }`);
+ });
+
+g.test('after_default_case')
+ .desc(`Test that a semicolon cannot be placed after a default switch case.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ false, `fn f() { switch 1 { default {}; } }`);
+ t.expectCompileResult(/* pass */ true, `fn f() { switch 1 { default {} } }`);
+ });
+
+g.test('after_default_case_break')
+ .desc(`Test that a semicolon cannot be placed after a default switch case.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ false, `fn f() { switch 1 { default { break } } }`);
+ t.expectCompileResult(/* pass */ true, `fn f() { switch 1 { default { break; } } }`);
+ });
+
+g.test('after_for')
+ .desc(`Test that a semicolon can be placed after a for-loop.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { for (; false;) {}; }`);
+ });
+
+g.test('after_for_break')
+ .desc(`Test that a semicolon must be placed after a for-loop break statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { for (; false;) { break; } }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { for (; false;) { break } }`);
+ });
+
+g.test('after_loop')
+ .desc(`Test that a semicolon can be placed after a loop.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { loop { break; }; }`);
+ });
+
+g.test('after_loop_break')
+ .desc(`Test that a semicolon must be placed after a loop break statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { loop { break; }; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { loop { break }; }`);
+ });
+
+g.test('after_loop_break_if')
+ .desc(`Test that a semicolon must be placed after a loop break-if statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { loop { continuing { break if true; } }; }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { loop { continuing { break if true } }; }`);
+ });
+
+g.test('after_loop_continue')
+ .desc(`Test that a semicolon must be placed after a loop continue statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { loop { if true { continue; } { break; } } }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { loop { if true { continue } { break; } } }`);
+ });
+
+g.test('after_continuing')
+ .desc(`Test that a semicolon cannot be placed after a continuing.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ false, `fn f() { loop { break; continuing{}; } }`);
+ t.expectCompileResult(/* pass */ true, `fn f() { loop { break; continuing{} } }`);
+ });
+
+g.test('after_while')
+ .desc(`Test that a semicolon cannot be placed after a while-loop.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { while false {}; }`);
+ });
+
+g.test('after_while_break')
+ .desc(`Test that a semicolon must be placed after a while break statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { while false { break; } }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { while false { break } }`);
+ });
+
+g.test('after_while_continue')
+ .desc(`Test that a semicolon must be placed after a while continue statement.`)
+ .fn(t => {
+ t.expectCompileResult(/* pass */ true, `fn f() { while false { continue; } }`);
+ t.expectCompileResult(/* pass */ false, `fn f() { while false { continue } }`);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/source.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/source.spec.js
new file mode 100644
index 0000000000..b4cfe94b24
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/source.spec.js
@@ -0,0 +1,30 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for source parsing`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('valid_source')
+ .desc(`Tests that a valid source is consumed successfully.`)
+ .fn(t => {
+ const code = `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(.4, .2, .3, .1);
+ }`;
+ t.expectCompileResult(true, code);
+ });
+
+g.test('empty')
+ .desc(`Test that an empty source is consumed successfully.`)
+ .fn(t => {
+ t.expectCompileResult(true, '');
+ });
+
+g.test('invalid_source')
+ .desc(`Tests that a source which does not match the grammar fails.`)
+ .fn(t => {
+ t.expectCompileResult(false, 'invalid_source');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/static_assert.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/static_assert.spec.js
new file mode 100644
index 0000000000..829ce1146c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/static_assert.spec.js
@@ -0,0 +1,38 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Parser validation tests for static_assert`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kCases = {
+ no_parentheses: { code: `static_assert true;`, pass: true },
+ left_parenthesis_only: { code: `static_assert(true;`, pass: false },
+ right_parenthesis_only: { code: `static_assert true);`, pass: false },
+ both_parentheses: { code: `static_assert(true);`, pass: true },
+ condition_on_newline: {
+ code: `static_assert
+true;`,
+ pass: true,
+ },
+ multiline_with_parentheses: {
+ code: `static_assert
+(
+ true
+);`,
+ pass: true,
+ },
+ invalid_expression: { code: `static_assert(1!2);`, pass: false },
+ no_condition_no_parentheses: { code: `static_assert;`, pass: false },
+ no_condition_with_parentheses: { code: `static_assert();`, pass: false },
+ not_a_boolean: { code: `static_assert 42;`, pass: false },
+};
+
+g.test('parse')
+ .desc(`Tests that the static_assert statement parses correctly.`)
+ .params(u => u.combine('case', Object.keys(kCases)).beginSubcases())
+ .fn(t => {
+ const c = kCases[t.params.case];
+ t.expectCompileResult(c.pass, c.code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/var_and_let.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/var_and_let.spec.js
new file mode 100644
index 0000000000..974af4d02a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/parse/var_and_let.spec.js
@@ -0,0 +1,73 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Positive and negative validation tests for variable and const.
+
+TODO: Find a better way to test arrays than using a single arbitrary size. [1]
+`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kTestTypes = [
+ 'f32',
+ 'i32',
+ 'u32',
+ 'bool',
+ 'vec2<f32>',
+ 'vec2<i32>',
+ 'vec2<u32>',
+ 'vec2<bool>',
+ 'vec3<f32>',
+ 'vec3<i32>',
+ 'vec3<u32>',
+ 'vec3<bool>',
+ 'vec4<f32>',
+ 'vec4<i32>',
+ 'vec4<u32>',
+ 'vec4<bool>',
+ 'mat2x2<f32>',
+ 'mat2x3<f32>',
+ 'mat2x4<f32>',
+ 'mat3x2<f32>',
+ 'mat3x3<f32>',
+ 'mat3x4<f32>',
+ 'mat4x2<f32>',
+ 'mat4x3<f32>',
+ 'mat4x4<f32>',
+ // [1]: 12 is a random number here. find a solution to replace it.
+ 'array<f32, 12>',
+ 'array<i32, 12>',
+ 'array<u32, 12>',
+ 'array<bool, 12>',
+];
+
+g.test('initializer_type')
+ .desc(
+ `
+ If present, the initializer's type must match the store type of the variable.
+ Testing scalars, vectors, and matrices of every dimension and type.
+ TODO: add test for: structs - arrays of vectors and matrices - arrays of different length
+`
+ )
+ .params(u =>
+ u
+ .combine('variableOrConstant', ['var', 'let'])
+ .beginSubcases()
+ .combine('lhsType', kTestTypes)
+ .combine('rhsType', kTestTypes)
+ )
+ .fn(t => {
+ const { variableOrConstant, lhsType, rhsType } = t.params;
+
+ const code = `
+ @fragment
+ fn main() {
+ ${variableOrConstant} a : ${lhsType} = ${rhsType}();
+ }
+ `;
+
+ const expectation = lhsType === rhsType;
+ t.expectCompileResult(expectation, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/bindings.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/bindings.spec.js
new file mode 100644
index 0000000000..546a0b0ce8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/bindings.spec.js
@@ -0,0 +1,114 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for resource interface bindings`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+import { declareEntrypoint, kResourceEmitters, kResourceKindsA, kResourceKindsB } from './util.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('single_entry_point')
+ .desc(
+ `Test that two different resource variables in a shader must not have the same group and binding values, when considered as a pair.`
+ )
+ .params(u =>
+ u
+ .combine('stage', ['vertex', 'fragment', 'compute'])
+ .combine('a_kind', kResourceKindsA)
+ .combine('b_kind', kResourceKindsB)
+ .combine('a_group', [0, 3])
+ .combine('b_group', [0, 3])
+ .combine('a_binding', [0, 3])
+ .combine('b_binding', [0, 3])
+ .combine('usage', ['direct', 'transitive'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const resourceA = kResourceEmitters.get(t.params.a_kind);
+ const resourceB = kResourceEmitters.get(t.params.b_kind);
+ const resources = `
+${resourceA('resource_a', t.params.a_group, t.params.a_binding)}
+${resourceB('resource_b', t.params.b_group, t.params.b_binding)}
+`;
+ const expect =
+ t.params.a_group !== t.params.b_group || t.params.a_binding !== t.params.b_binding;
+
+ if (t.params.usage === 'direct') {
+ const code = `
+${resources}
+${declareEntrypoint('main', t.params.stage, '_ = resource_a; _ = resource_b;')}
+`;
+ t.expectCompileResult(expect, code);
+ } else {
+ const code = `
+${resources}
+fn use_a() { _ = resource_a; }
+fn use_b() { _ = resource_b; }
+${declareEntrypoint('main', t.params.stage, 'use_a(); use_b();')}
+`;
+ t.expectCompileResult(expect, code);
+ }
+ });
+
+g.test('different_entry_points')
+ .desc(
+ `Test that resources may use the same binding points if exclusively accessed by different entry points.`
+ )
+ .params(u =>
+ u
+ .combine('a_stage', ['vertex', 'fragment', 'compute'])
+ .combine('b_stage', ['vertex', 'fragment', 'compute'])
+ .combine('a_kind', kResourceKindsA)
+ .combine('b_kind', kResourceKindsB)
+ .combine('usage', ['direct', 'transitive'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const resourceA = kResourceEmitters.get(t.params.a_kind);
+ const resourceB = kResourceEmitters.get(t.params.b_kind);
+ const resources = `
+${resourceA('resource_a', /* group */ 0, /* binding */ 0)}
+${resourceB('resource_b', /* group */ 0, /* binding */ 0)}
+`;
+ const expect = true; // Binding reuse between different entry points is fine.
+
+ if (t.params.usage === 'direct') {
+ const code = `
+${resources}
+${declareEntrypoint('main_a', t.params.a_stage, '_ = resource_a;')}
+${declareEntrypoint('main_b', t.params.b_stage, '_ = resource_b;')}
+`;
+ t.expectCompileResult(expect, code);
+ } else {
+ const code = `
+${resources}
+fn use_a() { _ = resource_a; }
+fn use_b() { _ = resource_b; }
+${declareEntrypoint('main_a', t.params.a_stage, 'use_a();')}
+${declareEntrypoint('main_b', t.params.b_stage, 'use_b();')}
+`;
+ t.expectCompileResult(expect, code);
+ }
+ });
+
+g.test('binding_attributes')
+ .desc(`Test that both @group and @binding attributes must both be declared.`)
+ .params(u =>
+ u
+ .combine('stage', ['vertex', 'fragment', 'compute'])
+ .combine('has_group', [true, false])
+ .combine('has_binding', [true, false])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const emitter = kResourceEmitters.get('uniform');
+ const code = emitter(
+ 'R',
+ t.params.has_group ? 0 : undefined,
+ t.params.has_binding ? 0 : undefined
+ );
+
+ const expect = t.params.has_group && t.params.has_binding;
+ t.expectCompileResult(expect, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/util.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/util.js
new file mode 100644
index 0000000000..6c16a1ff04
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/resource_interface/util.js
@@ -0,0 +1,88 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+
+/** Helper function for emitting a resource declaration's group and binding attributes */
+function groupAndBinding(group, binding) {
+ return (
+ `${group !== undefined ? `@group(${group})` : '/* no group */'} ` +
+ `${binding !== undefined ? `@binding(${binding})` : '/* no binding */'}`
+ );
+}
+
+/** Helper function for emitting a resource declaration for the given type */
+function basicEmitter(type) {
+ return (name, group, binding) => `${groupAndBinding(group, binding)} var ${name} : ${type};\n`;
+}
+
+/** Map of resource declaration name, to an emitter. */
+export const kResourceEmitters = new Map([
+ ['texture_1d', basicEmitter('texture_1d<i32>')],
+ ['texture_2d', basicEmitter('texture_2d<i32>')],
+ ['texture_2d_array', basicEmitter('texture_2d_array<f32>')],
+ ['texture_3d', basicEmitter('texture_3d<i32>')],
+ ['texture_cube', basicEmitter('texture_cube<u32>')],
+ ['texture_cube_array', basicEmitter('texture_cube_array<u32>')],
+ ['texture_multisampled_2d', basicEmitter('texture_multisampled_2d<i32>')],
+ ['texture_external', basicEmitter('texture_external')],
+ ['texture_storage_1d', basicEmitter('texture_storage_1d<rgba8unorm, write>')],
+ ['texture_storage_2d', basicEmitter('texture_storage_2d<rgba8sint, write>')],
+ ['texture_storage_2d_array', basicEmitter('texture_storage_2d_array<r32uint, write>')],
+ ['texture_storage_3d', basicEmitter('texture_storage_3d<rg32uint, write>')],
+ ['texture_depth_2d', basicEmitter('texture_depth_2d')],
+ ['texture_depth_2d_array', basicEmitter('texture_depth_2d_array')],
+ ['texture_depth_cube', basicEmitter('texture_depth_cube')],
+ ['texture_depth_cube_array', basicEmitter('texture_depth_cube_array')],
+ ['texture_depth_multisampled_2d', basicEmitter('texture_depth_multisampled_2d')],
+ ['sampler', basicEmitter('sampler')],
+ ['sampler_comparison', basicEmitter('sampler_comparison')],
+ [
+ 'uniform',
+ (name, group, binding) =>
+ `${groupAndBinding(group, binding)} var<uniform> ${name} : array<vec4<f32>, 16>;\n`,
+ ],
+
+ [
+ 'storage',
+ (name, group, binding) =>
+ `${groupAndBinding(group, binding)} var<storage> ${name} : array<vec4<f32>, 16>;\n`,
+ ],
+]);
+
+/** A small selection of resource declaration names, which can be used in test permutations */
+export const kResourceKindsA = ['storage', 'texture_2d', 'texture_external', 'uniform'];
+
+/** A small selection of resource declaration names, which can be used in test permutations */
+export const kResourceKindsB = ['texture_3d', 'texture_storage_1d', 'uniform'];
+
+/** An enumerator of shader stages */
+
+/**
+ * declareEntrypoint emits the WGSL to declare an entry point with the given name, stage and body.
+ * The generated function will have an appropriate return type and return statement, so that @p body
+ * does not have to change between stage.
+ * @param name the entry point function name
+ * @param stage the entry point stage
+ * @param body the body of the function (excluding any automatically suffixed return statements)
+ * @returns the WGSL string for the entry point
+ */
+export function declareEntrypoint(name, stage, body) {
+ switch (stage) {
+ case 'vertex':
+ return `@vertex
+fn ${name}() -> @builtin(position) vec4f {
+ ${body}
+ return vec4f();
+}`;
+ case 'fragment':
+ return `@fragment
+fn ${name}() {
+ ${body}
+}`;
+ case 'compute':
+ return `@compute @workgroup_size(1)
+fn ${name}() {
+ ${body}
+}`;
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js
new file mode 100644
index 0000000000..3b098cee18
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/builtins.spec.js
@@ -0,0 +1,277 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for entry point built-in variables`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+import { generateShader } from './util.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+// List of all built-in variables and their stage, in|out usage, and type.
+// Taken from table in Section 15:
+// https://www.w3.org/TR/2021/WD-WGSL-20211013/#builtin-variables
+export const kBuiltins = [
+ { name: 'vertex_index', stage: 'vertex', io: 'in', type: 'u32' },
+ { name: 'instance_index', stage: 'vertex', io: 'in', type: 'u32' },
+ { name: 'position', stage: 'vertex', io: 'out', type: 'vec4<f32>' },
+ { name: 'position', stage: 'fragment', io: 'in', type: 'vec4<f32>' },
+ { name: 'front_facing', stage: 'fragment', io: 'in', type: 'bool' },
+ { name: 'frag_depth', stage: 'fragment', io: 'out', type: 'f32' },
+ { name: 'local_invocation_id', stage: 'compute', io: 'in', type: 'vec3<u32>' },
+ { name: 'local_invocation_index', stage: 'compute', io: 'in', type: 'u32' },
+ { name: 'global_invocation_id', stage: 'compute', io: 'in', type: 'vec3<u32>' },
+ { name: 'workgroup_id', stage: 'compute', io: 'in', type: 'vec3<u32>' },
+ { name: 'num_workgroups', stage: 'compute', io: 'in', type: 'vec3<u32>' },
+ { name: 'sample_index', stage: 'fragment', io: 'in', type: 'u32' },
+ { name: 'sample_mask', stage: 'fragment', io: 'in', type: 'u32' },
+ { name: 'sample_mask', stage: 'fragment', io: 'out', type: 'u32' },
+];
+
+// List of types to test against.
+const kTestTypes = [
+ 'bool',
+ 'u32',
+ 'i32',
+ 'f32',
+ 'vec2<bool>',
+ 'vec2<u32>',
+ 'vec2<i32>',
+ 'vec2<f32>',
+ 'vec3<bool>',
+ 'vec3<u32>',
+ 'vec3<i32>',
+ 'vec3<f32>',
+ 'vec4<bool>',
+ 'vec4<u32>',
+ 'vec4<i32>',
+ 'vec4<f32>',
+ 'mat2x2<f32>',
+ 'mat2x3<f32>',
+ 'mat2x4<f32>',
+ 'mat3x2<f32>',
+ 'mat3x3<f32>',
+ 'mat3x4<f32>',
+ 'mat4x2<f32>',
+ 'mat4x3<f32>',
+ 'mat4x4<f32>',
+ 'atomic<u32>',
+ 'atomic<i32>',
+ 'array<bool,4>',
+ 'array<u32,4>',
+ 'array<i32,4>',
+ 'array<f32,4>',
+ 'MyStruct',
+];
+
+g.test('stage_inout')
+ .desc(
+ `Test that each @builtin attribute is validated against the required stage and in/out usage for that built-in variable.`
+ )
+ .params(u =>
+ u
+ .combineWithParams(kBuiltins)
+ .combine('use_struct', [true, false])
+ .combine('target_stage', ['', 'vertex', 'fragment', 'compute'])
+ .combine('target_io', ['in', 'out'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const code = generateShader({
+ attribute: `@builtin(${t.params.name})`,
+ type: t.params.type,
+ stage: t.params.target_stage,
+ io: t.params.target_io,
+ use_struct: t.params.use_struct,
+ });
+
+ // Expect to pass iff the built-in table contains an entry that matches.
+ const expectation = kBuiltins.some(
+ x =>
+ x.name === t.params.name &&
+ (x.stage === t.params.target_stage ||
+ (t.params.use_struct && t.params.target_stage === '')) &&
+ (x.io === t.params.target_io || t.params.target_stage === '') &&
+ x.type === t.params.type
+ );
+
+ t.expectCompileResult(expectation, code);
+ });
+
+g.test('type')
+ .desc(
+ `Test that each @builtin attribute is validated against the required type of that built-in variable.`
+ )
+ .params(u =>
+ u
+ .combineWithParams(kBuiltins)
+ .combine('use_struct', [true, false])
+ .combine('target_type', kTestTypes)
+ .beginSubcases()
+ )
+ .fn(t => {
+ let code = '';
+
+ if (t.params.target_type === 'MyStruct') {
+ // Generate a struct that contains the correct built-in type.
+ code += 'struct MyStruct {\n';
+ code += ` value : ${t.params.type}\n`;
+ code += '};\n\n';
+ }
+
+ code += generateShader({
+ attribute: `@builtin(${t.params.name})`,
+ type: t.params.target_type,
+ stage: t.params.stage,
+ io: t.params.io,
+ use_struct: t.params.use_struct,
+ });
+
+ // Expect to pass iff the built-in table contains an entry that matches.
+ const expectation = kBuiltins.some(
+ x =>
+ x.name === t.params.name &&
+ x.stage === t.params.stage &&
+ x.io === t.params.io &&
+ x.type === t.params.target_type
+ );
+
+ t.expectCompileResult(expectation, code);
+ });
+
+g.test('nesting')
+ .desc(`Test validation of nested built-in variables`)
+ .params(u =>
+ u.combine('target_stage', ['fragment', '']).combine('target_io', ['in', 'out']).beginSubcases()
+ )
+ .fn(t => {
+ // Generate a struct that contains a sample_mask builtin, nested inside another struct.
+ let code = `
+ struct Inner {
+ @builtin(sample_mask) value : u32
+ };
+ struct Outer {
+ inner : Inner
+ };`;
+
+ code += generateShader({
+ attribute: '',
+ type: 'Outer',
+ stage: t.params.target_stage,
+ io: t.params.target_io,
+ use_struct: false,
+ });
+
+ // Expect to pass only if the struct is not used for entry point IO.
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('duplicates')
+ .desc(`Test that duplicated built-in variables are validated.`)
+ .params(u =>
+ u
+ // Place two @builtin(sample_mask) attributes onto the entry point function.
+ // We use `sample_mask` as it is valid as both an input and output for the same entry point.
+ // The function:
+ // - has two non-struct parameters (`p1` and `p2`)
+ // - has two struct parameters each with two members (`s1{a,b}` and `s2{a,b}`)
+ // - returns a struct with two members (`ra` and `rb`)
+ // By default, all of these variables will have unique @location() attributes.
+ .combine('first', ['p1', 's1a', 's2a', 'ra'])
+ .combine('second', ['p2', 's1b', 's2b', 'rb'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const p1 =
+ t.params.first === 'p1' ? '@builtin(sample_mask)' : '@location(1) @interpolate(flat)';
+ const p2 =
+ t.params.second === 'p2' ? '@builtin(sample_mask)' : '@location(2) @interpolate(flat)';
+ const s1a =
+ t.params.first === 's1a' ? '@builtin(sample_mask)' : '@location(3) @interpolate(flat)';
+ const s1b =
+ t.params.second === 's1b' ? '@builtin(sample_mask)' : '@location(4) @interpolate(flat)';
+ const s2a =
+ t.params.first === 's2a' ? '@builtin(sample_mask)' : '@location(5) @interpolate(flat)';
+ const s2b =
+ t.params.second === 's2b' ? '@builtin(sample_mask)' : '@location(6) @interpolate(flat)';
+ const ra =
+ t.params.first === 'ra' ? '@builtin(sample_mask)' : '@location(1) @interpolate(flat)';
+ const rb =
+ t.params.second === 'rb' ? '@builtin(sample_mask)' : '@location(2) @interpolate(flat)';
+ const code = `
+ struct S1 {
+ ${s1a} a : u32,
+ ${s1b} b : u32,
+ };
+ struct S2 {
+ ${s2a} a : u32,
+ ${s2b} b : u32,
+ };
+ struct R {
+ ${ra} a : u32,
+ ${rb} b : u32,
+ };
+ @fragment
+ fn main(${p1} p1 : u32,
+ ${p2} p2 : u32,
+ s1 : S1,
+ s2 : S2,
+ ) -> R {
+ return R();
+ }
+ `;
+
+ // The test should fail if both @builtin(sample_mask) attributes are on the input parameters
+ // or structures, or it they are both on the output struct. Otherwise it should pass.
+ const firstIsRet = t.params.first === 'ra';
+ const secondIsRet = t.params.second === 'rb';
+ const expectation = firstIsRet !== secondIsRet;
+ t.expectCompileResult(expectation, code);
+ });
+
+g.test('missing_vertex_position')
+ .desc(`Test that vertex shaders are required to output @builtin(position).`)
+ .params(u =>
+ u
+ .combine('use_struct', [true, false])
+ .combine('attribute', ['@builtin(position)', '@location(0)'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const code = `
+ struct S {
+ ${t.params.attribute} value : vec4<f32>
+ };
+
+ @vertex
+ fn main() -> ${t.params.use_struct ? 'S' : `${t.params.attribute} vec4<f32>`} {
+ return ${t.params.use_struct ? 'S' : 'vec4<f32>'}();
+ }
+ `;
+
+ // Expect to pass only when using @builtin(position).
+ t.expectCompileResult(t.params.attribute === '@builtin(position)', code);
+ });
+
+g.test('reuse_builtin_name')
+ .desc(`Test that a builtin name can be used in different contexts`)
+ .params(u =>
+ u
+ .combineWithParams(kBuiltins)
+ .combine('use', ['type_name', 'struct', 'function', 'module-var', 'function-var'])
+ )
+ .fn(t => {
+ let code = '';
+ if (t.params.use === 'type_name') {
+ code += `type ${t.params.name} = i32;`;
+ } else if (t.params.use === `struct`) {
+ code += `struct ${t.params.name} { i: f32, }`;
+ } else if (t.params.use === `function`) {
+ code += `fn ${t.params.name}() {}`;
+ } else if (t.params.use === `module-var`) {
+ code += `const ${t.params.name} = 1;`;
+ } else if (t.params.use === `function-var`) {
+ code += `fn test() { let ${t.params.name} = 1; }`;
+ }
+ t.expectCompileResult(true, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/entry_point.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/entry_point.spec.js
new file mode 100644
index 0000000000..982e4e3dc9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/entry_point.spec.js
@@ -0,0 +1,138 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for attributes and entry point requirements`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('missing_attribute_on_param')
+ .desc(`Test that an entry point without an IO attribute on one of its parameters is rejected.`)
+ .params(u => u.combine('target_stage', ['', 'vertex', 'fragment', 'compute']).beginSubcases())
+ .fn(t => {
+ const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';
+ const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';
+ const compute_attr = t.params.target_stage === 'compute' ? '' : '@builtin(workgroup_id)';
+ const code = `
+@vertex
+fn vert_main(@location(0) a : f32,
+ ${vertex_attr} b : f32,
+@ location(2) c : f32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+
+@fragment
+fn frag_main(@location(0) a : f32,
+ ${fragment_attr} b : f32,
+@ location(2) c : f32) {
+}
+
+@compute @workgroup_size(1)
+fn comp_main(@builtin(global_invocation_id) a : vec3<u32>,
+ ${compute_attr} b : vec3<u32>,
+ @builtin(local_invocation_id) c : vec3<u32>) {
+}
+`;
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('missing_attribute_on_param_struct')
+ .desc(
+ `Test that an entry point struct parameter without an IO attribute on one of its members is rejected.`
+ )
+ .params(u => u.combine('target_stage', ['', 'vertex', 'fragment', 'compute']).beginSubcases())
+ .fn(t => {
+ const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';
+ const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';
+ const compute_attr = t.params.target_stage === 'compute' ? '' : '@builtin(workgroup_id)';
+ const code = `
+struct VertexInputs {
+ @location(0) a : f32,
+ ${vertex_attr} b : f32,
+@ location(2) c : f32,
+};
+struct FragmentInputs {
+ @location(0) a : f32,
+ ${fragment_attr} b : f32,
+@ location(2) c : f32,
+};
+struct ComputeInputs {
+ @builtin(global_invocation_id) a : vec3<u32>,
+ ${compute_attr} b : vec3<u32>,
+ @builtin(local_invocation_id) c : vec3<u32>,
+};
+
+@vertex
+fn vert_main(inputs : VertexInputs) -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+
+@fragment
+fn frag_main(inputs : FragmentInputs) {
+}
+
+@compute @workgroup_size(1)
+fn comp_main(inputs : ComputeInputs) {
+}
+`;
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('missing_attribute_on_return_type')
+ .desc(`Test that an entry point without an IO attribute on its return type is rejected.`)
+ .params(u => u.combine('target_stage', ['', 'vertex', 'fragment']).beginSubcases())
+ .fn(t => {
+ const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@builtin(position)';
+ const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(0)';
+ const code = `
+@vertex
+fn vert_main() -> ${vertex_attr} vec4<f32> {
+ return vec4<f32>();
+}
+
+@fragment
+fn frag_main() -> ${fragment_attr} vec4<f32> {
+ return vec4<f32>();
+}
+`;
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('missing_attribute_on_return_type_struct')
+ .desc(
+ `Test that an entry point struct return type without an IO attribute on one of its members is rejected.`
+ )
+ .params(u => u.combine('target_stage', ['', 'vertex', 'fragment']).beginSubcases())
+ .fn(t => {
+ const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';
+ const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';
+ const code = `
+struct VertexOutputs {
+ @location(0) a : f32,
+ ${vertex_attr} b : f32,
+ @builtin(position) c : vec4<f32>,
+};
+struct FragmentOutputs {
+ @location(0) a : f32,
+ ${fragment_attr} b : f32,
+@ location(2) c : f32,
+};
+
+@vertex
+fn vert_main() -> VertexOutputs {
+ return VertexOutputs();
+}
+
+@fragment
+fn frag_main() -> FragmentOutputs {
+ return FragmentOutputs();
+}
+`;
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('no_entry_point_provided')
+ .desc(`Tests that a shader without an entry point is accepted`)
+ .fn(t => {
+ t.expectCompileResult(true, 'fn main() {}');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/interpolate.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/interpolate.spec.js
new file mode 100644
index 0000000000..28088f9dcf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/interpolate.spec.js
@@ -0,0 +1,145 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for the interpolate attribute`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+import { generateShader } from './util.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+// List of valid interpolation attributes.
+const kValidInterpolationAttributes = new Set([
+ '',
+ '@interpolate(flat)',
+ '@interpolate(perspective)',
+ '@interpolate(perspective, center)',
+ '@interpolate(perspective, centroid)',
+ '@interpolate(perspective, sample)',
+ '@interpolate(linear)',
+ '@interpolate(linear, center)',
+ '@interpolate(linear, centroid)',
+ '@interpolate(linear, sample)',
+]);
+
+g.test('type_and_sampling')
+ .desc(`Test that all combinations of interpolation type and sampling are validated correctly.`)
+ .params(u =>
+ u
+ .combine('stage', ['vertex', 'fragment'])
+ .combine('io', ['in', 'out'])
+ .combine('use_struct', [true, false])
+ .combine('type', [
+ '',
+ 'flat',
+ 'perspective',
+ 'linear',
+ 'center', // Invalid as first param
+ 'centroid', // Invalid as first param
+ 'sample', // Invalid as first param
+ ])
+ .combine('sampling', [
+ '',
+ 'center',
+ 'centroid',
+ 'sample',
+ 'flat', // Invalid as second param
+ 'perspective', // Invalid as second param
+ 'linear', // Invalid as second param
+ ])
+ .beginSubcases()
+ )
+ .fn(t => {
+ if (t.params.stage === 'vertex' && t.params.use_struct === false) {
+ t.skip('vertex output must include a position builtin, so must use a struct');
+ }
+
+ let interpolate = '';
+ if (t.params.type !== '' || t.params.sampling !== '') {
+ interpolate = '@interpolate(';
+ if (t.params.type !== '') {
+ interpolate += `${t.params.type}`;
+ }
+ if (t.params.sampling !== '') {
+ interpolate += `, ${t.params.sampling}`;
+ }
+ interpolate += `)`;
+ }
+ const code = generateShader({
+ attribute: '@location(0)' + interpolate,
+ type: 'f32',
+ stage: t.params.stage,
+ io: t.params.io,
+ use_struct: t.params.use_struct,
+ });
+
+ t.expectCompileResult(kValidInterpolationAttributes.has(interpolate), code);
+ });
+
+g.test('require_location')
+ .desc(`Test that the interpolate attribute is only accepted with user-defined IO.`)
+ .params(u =>
+ u
+ .combine('stage', ['vertex', 'fragment'])
+ .combine('attribute', ['@location(0)', '@builtin(position)'])
+ .combine('use_struct', [true, false])
+ .beginSubcases()
+ )
+ .fn(t => {
+ if (
+ t.params.stage === 'vertex' &&
+ t.params.use_struct === false &&
+ !t.params.attribute.includes('position')
+ ) {
+ t.skip('vertex output must include a position builtin, so must use a struct');
+ }
+
+ const code = generateShader({
+ attribute: t.params.attribute + `@interpolate(flat)`,
+ type: 'vec4<f32>',
+ stage: t.params.stage,
+ io: t.params.stage === 'fragment' ? 'in' : 'out',
+ use_struct: t.params.use_struct,
+ });
+ t.expectCompileResult(t.params.attribute === '@location(0)', code);
+ });
+
+g.test('integral_types')
+ .desc(`Test that the implementation requires @interpolate(flat) for integral user-defined IO.`)
+ .params(u =>
+ u
+ .combine('stage', ['vertex', 'fragment'])
+ .combine('type', ['i32', 'u32', 'vec2<i32>', 'vec4<u32>'])
+ .combine('use_struct', [true, false])
+ .combine('attribute', kValidInterpolationAttributes)
+ .beginSubcases()
+ )
+ .fn(t => {
+ if (t.params.stage === 'vertex' && t.params.use_struct === false) {
+ t.skip('vertex output must include a position builtin, so must use a struct');
+ }
+
+ const code = generateShader({
+ attribute: '@location(0)' + t.params.attribute,
+ type: t.params.type,
+ stage: t.params.stage,
+ io: t.params.stage === 'vertex' ? 'out' : 'in',
+ use_struct: t.params.use_struct,
+ });
+
+ t.expectCompileResult(t.params.attribute === '@interpolate(flat)', code);
+ });
+
+g.test('duplicate')
+ .desc(`Test that the interpolate attribute can only be applied once.`)
+ .params(u => u.combine('attr', ['', '@interpolate(flat)']))
+ .fn(t => {
+ const code = generateShader({
+ attribute: `@location(0) @interpolate(flat) ${t.params.attr}`,
+ type: 'vec4<f32>',
+ stage: 'fragment',
+ io: 'in',
+ use_struct: false,
+ });
+ t.expectCompileResult(t.params.attr === '', code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/invariant.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/invariant.spec.js
new file mode 100644
index 0000000000..1729502082
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/invariant.spec.js
@@ -0,0 +1,84 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for the invariant attribute`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+import { kBuiltins } from './builtins.spec.js';
+import { generateShader } from './util.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+g.test('valid_only_with_vertex_position_builtin')
+ .desc(`Test that the invariant attribute is only accepted with the vertex position builtin`)
+ .params(u => u.combineWithParams(kBuiltins).combine('use_struct', [true, false]).beginSubcases())
+ .fn(t => {
+ const code = generateShader({
+ attribute: `@builtin(${t.params.name}) @invariant`,
+ type: t.params.type,
+ stage: t.params.stage,
+ io: t.params.io,
+ use_struct: t.params.use_struct,
+ });
+
+ t.expectCompileResult(t.params.name === 'position', code);
+ });
+
+g.test('not_valid_on_user_defined_io')
+ .desc(`Test that the invariant attribute is not accepted on user-defined IO attributes.`)
+ .params(u => u.combine('use_invariant', [true, false]).beginSubcases())
+ .fn(t => {
+ const invariant = t.params.use_invariant ? '@invariant' : '';
+ const code = `
+ struct VertexOut {
+ @location(0) ${invariant} loc0 : vec4<f32>,
+ @builtin(position) position : vec4<f32>,
+ };
+ @vertex
+ fn main() -> VertexOut {
+ return VertexOut();
+ }
+ `;
+ t.expectCompileResult(!t.params.use_invariant, code);
+ });
+
+g.test('invalid_use_of_parameters')
+ .desc(`Test that no parameters are accepted for the invariant attribute`)
+ .params(u => u.combine('suffix', ['', '()', '(0)']).beginSubcases())
+ .fn(t => {
+ const code = `
+ struct VertexOut {
+ @builtin(position) @invariant${t.params.suffix} position : vec4<f32>
+ };
+ @vertex
+ fn main() -> VertexOut {
+ return VertexOut();
+ }
+ `;
+ t.expectCompileResult(t.params.suffix === '', code);
+ });
+
+g.test('duplicate')
+ .desc(`Test that the invariant attribute can only be applied once.`)
+ .params(u =>
+ u
+ .combineWithParams(kBuiltins)
+ .combine('use_struct', [true, false])
+ .combine('attr', ['', '@invariant'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ if (t.params.name !== 'position') {
+ t.skip('only valid with position');
+ }
+
+ const code = generateShader({
+ attribute: `@builtin(${t.params.name}) @invariant ${t.params.attr}`,
+ type: t.params.type,
+ stage: t.params.stage,
+ io: t.params.io,
+ use_struct: t.params.use_struct,
+ });
+
+ t.expectCompileResult(t.params.attr === '', code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js
new file mode 100644
index 0000000000..8335719941
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/locations.spec.js
@@ -0,0 +1,260 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for entry point user-defined IO`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+import { generateShader } from './util.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kValidLocationTypes = new Set([
+ 'f16',
+ 'f32',
+ 'i32',
+ 'u32',
+ 'vec2<f32>',
+ 'vec2<i32>',
+ 'vec2<u32>',
+ 'vec3<f32>',
+ 'vec3<i32>',
+ 'vec3<u32>',
+ 'vec4<f32>',
+ 'vec4<i32>',
+ 'vec4<u32>',
+ 'vec2h',
+ 'vec2f',
+ 'vec2i',
+ 'vec2u',
+ 'vec3h',
+ 'vec3f',
+ 'vec3i',
+ 'vec3u',
+ 'vec4h',
+ 'vec4f',
+ 'vec4i',
+ 'vec4u',
+ 'MyAlias',
+]);
+
+const kInvalidLocationTypes = new Set([
+ 'bool',
+ 'vec2<bool>',
+ 'vec3<bool>',
+ 'vec4<bool>',
+ 'mat2x2<f32>',
+ 'mat2x3<f32>',
+ 'mat2x4<f32>',
+ 'mat3x2<f32>',
+ 'mat3x3<f32>',
+ 'mat3x4<f32>',
+ 'mat4x2<f32>',
+ 'mat4x3<f32>',
+ 'mat4x4<f32>',
+ 'mat2x2f',
+ 'mat2x3f',
+ 'mat2x4f',
+ 'mat3x2f',
+ 'mat3x3f',
+ 'mat3x4f',
+ 'mat4x2f',
+ 'mat4x3f',
+ 'mat4x4f',
+ 'mat2x2h',
+ 'mat2x3h',
+ 'mat2x4h',
+ 'mat3x2h',
+ 'mat3x3h',
+ 'mat3x4h',
+ 'mat4x2h',
+ 'mat4x3h',
+ 'mat4x4h',
+ 'array<f32, 12>',
+ 'array<i32, 12>',
+ 'array<u32, 12>',
+ 'array<bool, 12>',
+ 'atomic<i32>',
+ 'atomic<u32>',
+ 'MyStruct',
+ 'texture_1d<i32>',
+ 'texture_2d<f32>',
+ 'texture_2d_array<i32>',
+ 'texture_3d<f32>',
+ 'texture_cube<u32>',
+ 'texture_cube_array<i32>',
+ 'texture_multisampled_2d<i32>',
+ 'texture_external',
+ 'texture_storage_1d<rgba8unorm, write>',
+ 'texture_storage_2d<rg32float, write>',
+ 'texture_storage_2d_array<r32float, write>',
+ 'texture_storage_3d<r32float, write>',
+ 'texture_depth_2d',
+ 'texture_depth_2d_array',
+ 'texture_depth_cube',
+ 'texture_depth_cube_array',
+ 'texture_depth_multisampled_2d',
+ 'sampler',
+ 'sampler_comparison',
+]);
+
+g.test('stage_inout')
+ .desc(`Test validation of user-defined IO stage and in/out usage`)
+ .params(u =>
+ u
+ .combine('use_struct', [true, false])
+ .combine('target_stage', ['vertex', 'fragment', 'compute'])
+ .combine('target_io', ['in', 'out'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const code = generateShader({
+ attribute: '@location(0)',
+ type: 'f32',
+ stage: t.params.target_stage,
+ io: t.params.target_io,
+ use_struct: t.params.use_struct,
+ });
+
+ // Expect to fail for compute shaders or when used as a non-struct vertex output (since the
+ // position built-in must also be specified).
+ const expectation =
+ t.params.target_stage === 'fragment' ||
+ (t.params.target_stage === 'vertex' && (t.params.target_io === 'in' || t.params.use_struct));
+ t.expectCompileResult(expectation, code);
+ });
+
+g.test('type')
+ .desc(`Test validation of user-defined IO types`)
+ .params(u =>
+ u
+ .combine('use_struct', [true, false])
+ .combine('type', new Set([...kValidLocationTypes, ...kInvalidLocationTypes]))
+ .beginSubcases()
+ )
+ .beforeAllSubcases(t => {
+ if (
+ t.params.type === 'f16' ||
+ ((t.params.type.startsWith('mat') || t.params.type.startsWith('vec')) &&
+ t.params.type.endsWith('h'))
+ ) {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ }
+ })
+ .fn(t => {
+ let code = '';
+
+ if (
+ t.params.type === 'f16' ||
+ ((t.params.type.startsWith('mat') || t.params.type.startsWith('vec')) &&
+ t.params.type.endsWith('h'))
+ ) {
+ code += 'enable f16;\n';
+ }
+
+ if (t.params.type === 'MyStruct') {
+ // Generate a struct that contains a valid type.
+ code += `struct MyStruct {
+ value : f32,
+ }
+ `;
+ }
+ if (t.params.type === 'MyAlias') {
+ code += 'type MyAlias = i32;\n';
+ }
+
+ code += generateShader({
+ attribute: '@location(0) @interpolate(flat)',
+ type: t.params.type,
+ stage: 'fragment',
+ io: 'in',
+ use_struct: t.params.use_struct,
+ });
+
+ t.expectCompileResult(kValidLocationTypes.has(t.params.type), code);
+ });
+
+g.test('nesting')
+ .desc(`Test validation of nested user-defined IO`)
+ .params(u =>
+ u
+ .combine('target_stage', ['vertex', 'fragment', ''])
+ .combine('target_io', ['in', 'out'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ let code = '';
+
+ // Generate a struct that contains a valid type.
+ code += `struct Inner {
+ @location(0) value : f32,
+ }
+ struct Outer {
+ inner : Inner,
+ }
+ `;
+
+ code += generateShader({
+ attribute: '',
+ type: 'Outer',
+ stage: t.params.target_stage,
+ io: t.params.target_io,
+ use_struct: false,
+ });
+
+ // Expect to pass only if the struct is not used for entry point IO.
+ t.expectCompileResult(t.params.target_stage === '', code);
+ });
+
+g.test('duplicates')
+ .desc(`Test that duplicated user-defined IO attributes are validated.`)
+ .params(u =>
+ u
+ // Place two @location(0) attributes onto the entry point function.
+ // The function:
+ // - has two non-struct parameters (`p1` and `p2`)
+ // - has two struct parameters each with two members (`s1{a,b}` and `s2{a,b}`)
+ // - returns a struct with two members (`ra` and `rb`)
+ // By default, all of these user-defined IO variables will have unique location attributes.
+ .combine('first', ['p1', 's1a', 's2a', 'ra'])
+ .combine('second', ['p2', 's1b', 's2b', 'rb'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const p1 = t.params.first === 'p1' ? '0' : '1';
+ const p2 = t.params.second === 'p2' ? '0' : '2';
+ const s1a = t.params.first === 's1a' ? '0' : '3';
+ const s1b = t.params.second === 's1b' ? '0' : '4';
+ const s2a = t.params.first === 's2a' ? '0' : '5';
+ const s2b = t.params.second === 's2b' ? '0' : '6';
+ const ra = t.params.first === 'ra' ? '0' : '1';
+ const rb = t.params.second === 'rb' ? '0' : '2';
+ const code = `
+ struct S1 {
+ @location(${s1a}) a : f32,
+ @location(${s1b}) b : f32,
+ };
+ struct S2 {
+ @location(${s2a}) a : f32,
+ @location(${s2b}) b : f32,
+ };
+ struct R {
+ @location(${ra}) a : f32,
+ @location(${rb}) b : f32,
+ };
+ @fragment
+ fn main(@location(${p1}) p1 : f32,
+ @location(${p2}) p2 : f32,
+ s1 : S1,
+ s2 : S2,
+ ) -> R {
+ return R();
+ }
+ `;
+
+ // The test should fail if both @location(0) attributes are on the input parameters or
+ // structures, or it they are both on the output struct. Otherwise it should pass.
+ const firstIsRet = t.params.first === 'ra';
+ const secondIsRet = t.params.second === 'rb';
+ const expectation = firstIsRet !== secondIsRet;
+ t.expectCompileResult(expectation, code);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/util.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/util.js
new file mode 100644
index 0000000000..3092eb8182
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_io/util.js
@@ -0,0 +1,68 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * Generate an entry point that uses an entry point IO variable.
+ *
+ * @param {Object} params
+ * @param params.attribute The entry point IO attribute.
+ * @param params.type The type to use for the entry point IO variable.
+ * @param params.stage The shader stage.
+ * @param params.io An "in|out" string specifying whether the entry point IO is an input or an output.
+ * @param params.use_struct True to wrap the entry point IO in a struct.
+ * @returns The generated shader code.
+ */ export function generateShader({ attribute, type, stage, io, use_struct }) {
+ let code = '';
+
+ if (use_struct) {
+ // Generate a struct that wraps the entry point IO variable.
+ code += 'struct S {\n';
+ code += ` ${attribute} value : ${type},\n`;
+ if (stage === 'vertex' && io === 'out' && !attribute.includes('builtin(position)')) {
+ // Add position builtin for vertex outputs.
+ code += ` @builtin(position) position : vec4<f32>,\n`;
+ }
+ code += '};\n\n';
+ }
+
+ if (stage !== '') {
+ // Generate the entry point attributes.
+ code += `@${stage}`;
+ if (stage === 'compute') {
+ code += ' @workgroup_size(1)';
+ }
+ }
+
+ // Generate the entry point parameter and return type.
+ let param = '';
+ let retType = '';
+ let retVal = '';
+ if (io === 'in') {
+ if (use_struct) {
+ param = `in : S`;
+ } else {
+ param = `${attribute} value : ${type}`;
+ }
+
+ // Vertex shaders must always return `@builtin(position)`.
+ if (stage === 'vertex') {
+ retType = `-> @builtin(position) vec4<f32>`;
+ retVal = `return vec4<f32>();`;
+ }
+ } else if (io === 'out') {
+ if (use_struct) {
+ retType = '-> S';
+ retVal = `return S();`;
+ } else {
+ retType = `-> ${attribute} ${type}`;
+ retVal = `return ${type}();`;
+ }
+ }
+
+ code += `
+ fn main(${param}) ${retType} {
+ ${retVal}
+ }
+ `;
+
+ return code;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_validation_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_validation_test.js
new file mode 100644
index 0000000000..1af49b1460
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/shader_validation_test.js
@@ -0,0 +1,77 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { ErrorWithExtra } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+/**
+ * Base fixture for WGSL shader validation tests.
+ */
+export class ShaderValidationTest extends GPUTest {
+ /**
+ * Add a test expectation for whether a createShaderModule call succeeds or not.
+ *
+ * @example
+ * ```ts
+ * t.expectCompileResult(true, `wgsl code`); // Expect success
+ * t.expectCompileResult(false, `wgsl code`); // Expect validation error with any error string
+ * ```
+ */
+ expectCompileResult(expectedResult, code) {
+ let shaderModule;
+ this.expectGPUError(
+ 'validation',
+ () => {
+ shaderModule = this.device.createShaderModule({ code });
+ },
+ expectedResult !== true
+ );
+
+ const error = new ErrorWithExtra('', () => ({ shaderModule }));
+ this.eventualAsyncExpectation(async () => {
+ const compilationInfo = await shaderModule.compilationInfo();
+
+ // MAINTENANCE_TODO: Pretty-print error messages with source context.
+ const messagesLog = compilationInfo.messages
+ .map(m => `${m.lineNum}:${m.linePos}: ${m.type}: ${m.message}`)
+ .join('\n');
+ error.extra.compilationInfo = compilationInfo;
+
+ if (compilationInfo.messages.some(m => m.type === 'error')) {
+ if (expectedResult) {
+ error.message = `Unexpected compilationInfo 'error' message.\n` + messagesLog;
+ this.rec.validationFailed(error);
+ } else {
+ error.message = `Found expected compilationInfo 'error' message.\n` + messagesLog;
+ this.rec.debug(error);
+ }
+ } else {
+ if (!expectedResult) {
+ error.message = `Missing expected compilationInfo 'error' message.\n` + messagesLog;
+ this.rec.validationFailed(error);
+ } else {
+ error.message = `No compilationInfo 'error' messages, as expected.\n` + messagesLog;
+ this.rec.debug(error);
+ }
+ }
+ });
+ }
+
+ /**
+ * Wraps the code fragment into an entry point.
+ *
+ * @example
+ * ```ts
+ * t.wrapInEntryPoint(`var i = 0;`);
+ * ```
+ */
+ wrapInEntryPoint(code, enabledExtensions = []) {
+ const enableDirectives = enabledExtensions.map(x => `enable ${x};`).join('\n ');
+
+ return `
+ ${enableDirectives}
+
+ @compute @workgroup_size(1)
+ fn main() {
+ ${code}
+ }`;
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/static_assert/static_assert.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/static_assert/static_assert.spec.js
new file mode 100644
index 0000000000..5d8284f0cb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/validation/static_assert/static_assert.spec.js
@@ -0,0 +1,71 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Validation tests for static_assert`;
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+/**
+ * Builds a static_assert() statement, which checks that @p expr is equal to @p expect_true.
+ * @param expect_true true if @p expr should evaluate to true
+ * @param expr the constant expression
+ * @param scope module-scope or function-scope constant expression
+ * @returns the WGSL code
+ */
+function buildStaticAssert(expect_true, expr, scope) {
+ const stmt = expect_true ? `static_assert ${expr};` : `static_assert !(${expr});`;
+ return scope === 'module' ? stmt : `fn f() { ${stmt} }`;
+}
+
+const kConditionCases = {
+ true_literal: `true`,
+ not_false: `!false`,
+ const_eq_literal_int: `one == 1`,
+ const_eq_literal_float: `one == 1.0`,
+ binary_op_eq_const: `one+1 == two`,
+ any: `any(vec3(false, true, false))`,
+ min_max: `min(three, max(two, one)) == 2`,
+};
+
+g.test('constant_expression')
+ .desc(`Test that static_assert validates the condition expression.`)
+ .params(u =>
+ u
+ .combine('case', Object.keys(kConditionCases))
+ .combine('scope', ['module', 'function'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const constants = `
+const one = 1;
+const two = 2;
+const three = 2;
+`;
+ const expr = kConditionCases[t.params.case];
+ t.expectCompileResult(true, constants + buildStaticAssert(true, expr, t.params.scope));
+ t.expectCompileResult(false, constants + buildStaticAssert(false, expr, t.params.scope));
+ });
+
+g.test('evaluation_stage')
+ .desc(`Test that the static_assert expression must be a constant expression.`)
+ .params(u =>
+ u
+ .combine('scope', ['module', 'function'])
+ .combine('stage', ['constant', 'override', 'runtime'])
+ .beginSubcases()
+ )
+ .fn(t => {
+ const staticAssert = buildStaticAssert(true, 'value', t.params.scope);
+ switch (t.params.stage) {
+ case 'constant':
+ t.expectCompileResult(true, `const value = true;\n${staticAssert}`);
+ break;
+ case 'override':
+ t.expectCompileResult(false, `override value = true;\n${staticAssert}`);
+ break;
+ case 'runtime':
+ t.expectCompileResult(false, `var<private> value = true;\n${staticAssert}`);
+ break;
+ }
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/values.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/values.js
new file mode 100644
index 0000000000..9ca24c64b9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/shader/values.js
@@ -0,0 +1,94 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `Special and sample values for WGSL scalar types`;
+import { assert } from '../../common/util/util.js';
+import { uint32ToFloat32 } from '../util/conversion.js';
+
+/** Returns an array of subnormal f32 numbers.
+ * Subnormals are non-zero finite numbers with the minimum representable
+ * exponent.
+ */
+export function subnormalF32Examples() {
+ // The results, as uint32 values.
+ const result_as_bits = [];
+
+ const max_mantissa = 0x7f_ffff;
+ const sign_bits = [0, 0x8000_0000];
+ for (const sign_bit of sign_bits) {
+ // exponent bits must be zero.
+ const sign_and_exponent = sign_bit;
+
+ // Set all bits
+ result_as_bits.push(sign_and_exponent | max_mantissa);
+
+ // Set each of the lower bits individually.
+ for (let lower_bits = 1; lower_bits <= max_mantissa; lower_bits <<= 1) {
+ result_as_bits.push(sign_and_exponent | lower_bits);
+ }
+ }
+ assert(
+ result_as_bits.length === 2 * (1 + 23),
+ 'subnormal number sample count is ' + result_as_bits.length.toString()
+ );
+
+ return result_as_bits.map(u => uint32ToFloat32(u));
+}
+
+/** Returns an array of normal f32 numbers.
+ * Normal numbers are not: zero, Nan, infinity, subnormal.
+ */
+export function normalF32Examples() {
+ const result = [1.0, -2.0];
+
+ const max_mantissa_as_bits = 0x7f_ffff;
+ const min_exponent_as_bits = 0x0080_0000;
+ const max_exponent_as_bits = 0x7f00_0000; // Max normal exponent
+ const sign_bits = [0, 0x8000_0000];
+ for (const sign_bit of sign_bits) {
+ for (let e = min_exponent_as_bits; e <= max_exponent_as_bits; e += min_exponent_as_bits) {
+ const sign_and_exponent = sign_bit | e;
+
+ // Set zero mantissa bits
+ result.push(uint32ToFloat32(sign_and_exponent));
+ // Set all mantissa bits
+ result.push(uint32ToFloat32(sign_and_exponent | max_mantissa_as_bits));
+
+ // Set each of the lower bits individually.
+ for (let lower_bits = 1; lower_bits <= max_mantissa_as_bits; lower_bits <<= 1) {
+ result.push(uint32ToFloat32(sign_and_exponent | lower_bits));
+ }
+ }
+ }
+ assert(
+ result.length === 2 + 2 * 254 * 25,
+ 'normal number sample count is ' + result.length.toString()
+ );
+
+ return result;
+}
+
+/** Returns an array of 32-bit NaNs, as Uint32 bit patterns.
+ * NaNs have: maximum exponent, but the mantissa is not zero.
+ */
+export function nanF32BitsExamples() {
+ const result = [];
+ const exponent_bit = 0x7f80_0000;
+ const sign_bits = [0, 0x8000_0000];
+ for (const sign_bit of sign_bits) {
+ const sign_and_exponent = sign_bit | exponent_bit;
+ const bits = sign_and_exponent | 0x40_0000;
+ // Only the most significant bit of the mantissa is set.
+ result.push(bits);
+
+ // Quiet and signalling NaNs differ based on the most significant bit
+ // of the mantissa. Try both.
+ for (const quiet_signalling of [0, 0x40_0000]) {
+ // Set each of the lower bits.
+ for (let lower_bits = 1; lower_bits < 0x40_0000; lower_bits <<= 1) {
+ const bits = sign_and_exponent | quiet_signalling | lower_bits;
+ result.push(bits);
+ }
+ }
+ }
+ return result;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/buffer.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/buffer.js
new file mode 100644
index 0000000000..1da50c2699
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/buffer.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { memcpy } from '../../common/util/util.js';
+import { align } from './math.js';
+
+/**
+ * Creates a buffer with the contents of some TypedArray.
+ * The buffer size will always be aligned to 4 as we set mappedAtCreation === true when creating the
+ * buffer.
+ */
+export function makeBufferWithContents(device, dataArray, usage) {
+ const buffer = device.createBuffer({
+ mappedAtCreation: true,
+ size: align(dataArray.byteLength, 4),
+ usage,
+ });
+ memcpy({ src: dataArray }, { dst: buffer.getMappedRange() });
+ buffer.unmap();
+ return buffer;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js
new file mode 100644
index 0000000000..63da920b45
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/check_contents.js
@@ -0,0 +1,207 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // MAINTENANCE_TODO: The "checkThingTrue" naming is confusing; these must be used with `expectOK`
+// or the result is dropped on the floor. Rename these to things like `typedArrayIsOK`(??) to
+// make it clearer.
+// MAINTENANCE_TODO: Also, audit to make sure we aren't dropping any on the floor. Consider a
+// no-ignored-return lint check if we can find one that we can use.
+import { assert, ErrorWithExtra, iterRange, range } from '../../common/util/util.js';
+
+import { float16BitsToFloat32 } from './conversion.js';
+import { generatePrettyTable } from './pretty_diff_tables.js';
+
+/** Generate an expected value at `index`, to test for equality with the actual value. */
+
+/**
+ * Check whether two `TypedArray`s have equal contents.
+ * Returns `undefined` if the check passes, or an `Error` if not.
+ */
+export function checkElementsEqual(actual, expected) {
+ assert(actual.constructor === expected.constructor, 'TypedArray type mismatch');
+ assert(actual.length === expected.length, 'size mismatch');
+ return checkElementsEqualGenerated(actual, i => expected[i]);
+}
+
+/**
+ * Check whether each value in a `TypedArray` is between the two corresponding "expected" values
+ * (either `a(i) <= actual[i] <= b(i)` or `a(i) >= actual[i] => b(i)`).
+ */
+export function checkElementsBetween(actual, expected) {
+ const error = checkElementsPassPredicate(
+ actual,
+ (index, value) =>
+ value >= Math.min(expected[0](index), expected[1](index)) &&
+ value <= Math.max(expected[0](index), expected[1](index)),
+ {
+ predicatePrinter: [
+ { leftHeader: 'between', getValueForCell: index => expected[0](index) },
+ { leftHeader: 'and', getValueForCell: index => expected[1](index) },
+ ],
+ }
+ );
+
+ // If there was an error, extend it with additional extras.
+ return error ? new ErrorWithExtra(error, () => ({ expected })) : undefined;
+}
+
+/**
+ * Equivalent to {@link checkElementsBetween} but interpret values as float16 and convert to JS number before comparison.
+ */
+export function checkElementsFloat16Between(actual, expected) {
+ assert(actual.BYTES_PER_ELEMENT === 2, 'bytes per element need to be 2 (16bit)');
+ const actualF32 = new Float32Array(actual.length);
+ actual.forEach((v, i) => {
+ actualF32[i] = float16BitsToFloat32(v);
+ });
+ const expectedF32 = [new Float32Array(expected[0].length), new Float32Array(expected[1].length)];
+ expected[0].forEach((v, i) => {
+ expectedF32[0][i] = float16BitsToFloat32(v);
+ });
+ expected[1].forEach((v, i) => {
+ expectedF32[1][i] = float16BitsToFloat32(v);
+ });
+
+ const error = checkElementsPassPredicate(
+ actualF32,
+ (index, value) =>
+ value >= Math.min(expectedF32[0][index], expectedF32[1][index]) &&
+ value <= Math.max(expectedF32[0][index], expectedF32[1][index]),
+ {
+ predicatePrinter: [
+ { leftHeader: 'between', getValueForCell: index => expectedF32[0][index] },
+ { leftHeader: 'and', getValueForCell: index => expectedF32[1][index] },
+ ],
+ }
+ );
+
+ // If there was an error, extend it with additional extras.
+ return error ? new ErrorWithExtra(error, () => ({ expectedF32 })) : undefined;
+}
+
+/**
+ * Check whether each value in a `TypedArray` is equal to one of the two corresponding "expected"
+ * values (either `actual[i] === a[i]` or `actual[i] === b[i]`)
+ */
+export function checkElementsEqualEither(actual, expected) {
+ const error = checkElementsPassPredicate(
+ actual,
+ (index, value) => value === expected[0][index] || value === expected[1][index],
+ {
+ predicatePrinter: [
+ { leftHeader: 'either', getValueForCell: index => expected[0][index] },
+ { leftHeader: 'or', getValueForCell: index => expected[1][index] },
+ ],
+ }
+ );
+
+ // If there was an error, extend it with additional extras.
+ return error ? new ErrorWithExtra(error, () => ({ expected })) : undefined;
+}
+
+/**
+ * Check whether a `TypedArray`'s contents equal the values produced by a generator function.
+ * Returns `undefined` if the check passes, or an `Error` if not.
+ *
+ * ```text
+ * Array had unexpected contents at indices 2 through 19.
+ * Starting at index 1:
+ * actual == 0x: 00 fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00
+ * failed -> xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
+ * expected == 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * ```
+ *
+ * ```text
+ * Array had unexpected contents at indices 2 through 29.
+ * Starting at index 1:
+ * actual == 0.000 -2.000e+100 -1.000e+100 0.000 1.000e+100 2.000e+100 3.000e+100 4.000e+100 5.000e+100 6.000e+100 7.000e+100 ...
+ * failed -> xx xx xx xx xx xx xx xx xx ...
+ * expected == 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ...
+ * ```
+ */
+export function checkElementsEqualGenerated(actual, generator) {
+ const error = checkElementsPassPredicate(actual, (index, value) => value === generator(index), {
+ predicatePrinter: [{ leftHeader: 'expected ==', getValueForCell: index => generator(index) }],
+ });
+ // If there was an error, extend it with additional extras.
+ return error ? new ErrorWithExtra(error, () => ({ generator })) : undefined;
+}
+
+/**
+ * Check whether a `TypedArray`'s values pass the provided predicate function.
+ * Returns `undefined` if the check passes, or an `Error` if not.
+ */
+export function checkElementsPassPredicate(actual, predicate, { predicatePrinter }) {
+ const size = actual.length;
+ const ctor = actual.constructor;
+ const printAsFloat = ctor === Float32Array || ctor === Float64Array;
+
+ let failedElementsFirstMaybe = undefined;
+ /** Sparse array with `true` for elements that failed. */
+ const failedElements = [];
+ for (let i = 0; i < size; ++i) {
+ if (!predicate(i, actual[i])) {
+ failedElementsFirstMaybe ??= i;
+ failedElements[i] = true;
+ }
+ }
+
+ if (failedElementsFirstMaybe === undefined) {
+ return undefined;
+ }
+ const failedElementsFirst = failedElementsFirstMaybe;
+ const failedElementsLast = failedElements.length - 1;
+
+ // Include one extra non-failed element at the beginning and end (if they exist), for context.
+ const printElementsStart = Math.max(0, failedElementsFirst - 1);
+ const printElementsEnd = Math.min(size, failedElementsLast + 2);
+ const printElementsCount = printElementsEnd - printElementsStart;
+
+ const numberToString = printAsFloat
+ ? n => n.toPrecision(4)
+ : n => intToPaddedHex(n, { byteLength: ctor.BYTES_PER_ELEMENT });
+ const numberPrefix = printAsFloat ? '' : '0x:';
+
+ const printActual = actual.subarray(printElementsStart, printElementsEnd);
+ const printExpected = [];
+ if (predicatePrinter) {
+ for (const { leftHeader, getValueForCell: cell } of predicatePrinter) {
+ printExpected.push(
+ (function* () {
+ yield* [leftHeader, ''];
+ yield* iterRange(printElementsCount, i => cell(printElementsStart + i));
+ })()
+ );
+ }
+ }
+
+ const printFailedValueMarkers = (function* () {
+ yield* ['failed ->', ''];
+ yield* range(printElementsCount, i => (failedElements[printElementsStart + i] ? 'xx' : ''));
+ })();
+
+ const opts = {
+ fillToWidth: 120,
+ numberToString,
+ };
+ const msg = `Array had unexpected contents at indices ${failedElementsFirst} through ${failedElementsLast}.
+ Starting at index ${printElementsStart}:
+${generatePrettyTable(opts, [
+ ['actual ==', numberPrefix, ...printActual],
+ printFailedValueMarkers,
+ ...printExpected,
+])}`;
+ return new ErrorWithExtra(msg, () => ({
+ actual: actual.slice(),
+ }));
+}
+
+// Helper helpers
+
+/** Convert an integral `number` into a hex string, padded to the specified `byteLength`. */
+function intToPaddedHex(number, { byteLength }) {
+ assert(Number.isInteger(number), 'number must be integer');
+ let s = Math.abs(number).toString(16);
+ if (byteLength) s = s.padStart(byteLength * 2, '0');
+ if (number < 0) s = '-' + s;
+ return s;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js
new file mode 100644
index 0000000000..4f456fb7c5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/color_space_conversion.js
@@ -0,0 +1,241 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../common/util/util.js';
+import { multiplyMatrices } from './math.js';
+
+// These color space conversion function definitions are copied directly from
+// CSS Color Module Level 4 Sample Code: https://drafts.csswg.org/css-color/#color-conversion-code
+// *EXCEPT* the conversion matrices are replaced with exact rational forms computed here:
+// https://github.com/kainino0x/exact_css_xyz_matrices
+// using this Rust crate: https://crates.io/crates/rgb_derivation
+// as described for sRGB on this page: https://mina86.com/2019/srgb-xyz-matrix/
+// but using the numbers from the CSS spec: https://www.w3.org/TR/css-color-4/#predefined
+
+// Sample code for color conversions
+// Conversion can also be done using ICC profiles and a Color Management System
+// For clarity, a library is used for matrix multiplication (multiply-matrices.js)
+
+// sRGB-related functions
+
+/**
+ * convert an array of sRGB values
+ * where in-gamut values are in the range [0 - 1]
+ * to linear light (un-companded) form.
+ * https://en.wikipedia.org/wiki/SRGB
+ * Extended transfer function:
+ * for negative values, linear portion is extended on reflection of axis,
+ * then reflected power function is used.
+ */
+function lin_sRGB(RGB) {
+ return RGB.map(val => {
+ const sign = val < 0 ? -1 : 1;
+ const abs = Math.abs(val);
+
+ if (abs < 0.04045) {
+ return val / 12.92;
+ }
+
+ return sign * Math.pow((abs + 0.055) / 1.055, 2.4);
+ });
+}
+
+/**
+ * convert an array of linear-light sRGB values in the range 0.0-1.0
+ * to gamma corrected form
+ * https://en.wikipedia.org/wiki/SRGB
+ * Extended transfer function:
+ * For negative values, linear portion extends on reflection
+ * of axis, then uses reflected pow below that
+ */
+function gam_sRGB(RGB) {
+ return RGB.map(val => {
+ const sign = val < 0 ? -1 : 1;
+ const abs = Math.abs(val);
+
+ if (abs > 0.0031308) {
+ return sign * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);
+ }
+
+ return 12.92 * val;
+ });
+}
+
+/**
+ * convert an array of linear-light sRGB values to CIE XYZ
+ * using sRGB's own white, D65 (no chromatic adaptation)
+ */
+function lin_sRGB_to_XYZ(rgb) {
+ const M = [
+ [506752 / 1228815, 87881 / 245763, 12673 / 70218],
+ [87098 / 409605, 175762 / 245763, 12673 / 175545],
+ [7918 / 409605, 87881 / 737289, 1001167 / 1053270],
+ ];
+
+ return multiplyMatrices(M, rgb);
+}
+
+/**
+ * convert XYZ to linear-light sRGB
+ * using sRGB's own white, D65 (no chromatic adaptation)
+ */
+function XYZ_to_lin_sRGB(XYZ) {
+ const M = [
+ [12831 / 3959, -329 / 214, -1974 / 3959],
+ [-851781 / 878810, 1648619 / 878810, 36519 / 878810],
+ [705 / 12673, -2585 / 12673, 705 / 667],
+ ];
+
+ return multiplyMatrices(M, XYZ);
+}
+
+// display-p3-related functions
+
+/**
+ * convert an array of display-p3 RGB values in the range 0.0 - 1.0
+ * to linear light (un-companded) form.
+ */
+function lin_P3(RGB) {
+ return lin_sRGB(RGB); // same as sRGB
+}
+
+/**
+ * convert an array of linear-light display-p3 RGB in the range 0.0-1.0
+ * to gamma corrected form
+ */
+function gam_P3(RGB) {
+ return gam_sRGB(RGB); // same as sRGB
+}
+
+/**
+ * convert an array of linear-light display-p3 values to CIE XYZ
+ * using display-p3's D65 (no chromatic adaptation)
+ */
+function lin_P3_to_XYZ(rgb) {
+ const M = [
+ [608311 / 1250200, 189793 / 714400, 198249 / 1000160],
+ [35783 / 156275, 247089 / 357200, 198249 / 2500400],
+ [0 / 1, 32229 / 714400, 5220557 / 5000800],
+ ];
+
+ return multiplyMatrices(M, rgb);
+}
+
+/**
+ * convert XYZ to linear-light P3
+ * using display-p3's own white, D65 (no chromatic adaptation)
+ */
+function XYZ_to_lin_P3(XYZ) {
+ const M = [
+ [446124 / 178915, -333277 / 357830, -72051 / 178915],
+ [-14852 / 17905, 63121 / 35810, 423 / 17905],
+ [11844 / 330415, -50337 / 660830, 316169 / 330415],
+ ];
+
+ return multiplyMatrices(M, XYZ);
+}
+
+/**
+ * @returns the converted pixels in `{R: number, G: number, B: number, A: number}`.
+ *
+ * Follow conversion steps in CSS Color Module Level 4
+ * https://drafts.csswg.org/css-color/#predefined-to-predefined
+ * display-p3 and sRGB share the same white points.
+ */
+export function displayP3ToSrgb(pixel) {
+ assert(
+ pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined,
+ 'color space conversion requires all of R, G and B components'
+ );
+
+ let rgbVec = [pixel.R, pixel.G, pixel.B];
+ rgbVec = lin_P3(rgbVec);
+ let rgbMatrix = [[rgbVec[0]], [rgbVec[1]], [rgbVec[2]]];
+ rgbMatrix = XYZ_to_lin_sRGB(lin_P3_to_XYZ(rgbMatrix));
+ rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]];
+ rgbVec = gam_sRGB(rgbVec);
+
+ pixel.R = rgbVec[0];
+ pixel.G = rgbVec[1];
+ pixel.B = rgbVec[2];
+
+ return pixel;
+}
+/**
+ * @returns the converted pixels in `{R: number, G: number, B: number, A: number}`.
+ *
+ * Follow conversion steps in CSS Color Module Level 4
+ * https://drafts.csswg.org/css-color/#predefined-to-predefined
+ * display-p3 and sRGB share the same white points.
+ */
+export function srgbToDisplayP3(pixel) {
+ assert(
+ pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined,
+ 'color space conversion requires all of R, G and B components'
+ );
+
+ let rgbVec = [pixel.R, pixel.G, pixel.B];
+ rgbVec = lin_sRGB(rgbVec);
+ let rgbMatrix = [[rgbVec[0]], [rgbVec[1]], [rgbVec[2]]];
+ rgbMatrix = XYZ_to_lin_P3(lin_sRGB_to_XYZ(rgbMatrix));
+ rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]];
+ rgbVec = gam_P3(rgbVec);
+
+ pixel.R = rgbVec[0];
+ pixel.G = rgbVec[1];
+ pixel.B = rgbVec[2];
+
+ return pixel;
+}
+
+/**
+ * Returns a function which applies the specified colorspace/premultiplication conversion.
+ * Does not clamp, so may return values outside of the `dstColorSpace` gamut, due to either
+ * color space conversion or alpha premultiplication.
+ */
+export function makeInPlaceColorConversion({
+ srcPremultiplied,
+ dstPremultiplied,
+ srcColorSpace = 'srgb',
+ dstColorSpace = 'srgb',
+}) {
+ const requireColorSpaceConversion = srcColorSpace !== dstColorSpace;
+ const requireUnpremultiplyAlpha =
+ srcPremultiplied && (requireColorSpaceConversion || srcPremultiplied !== dstPremultiplied);
+ const requirePremultiplyAlpha =
+ dstPremultiplied && (requireColorSpaceConversion || srcPremultiplied !== dstPremultiplied);
+
+ return rgba => {
+ assert(rgba.A >= 0.0 && rgba.A <= 1.0, 'rgba.A out of bounds');
+
+ if (requireUnpremultiplyAlpha) {
+ if (rgba.A !== 0.0) {
+ rgba.R /= rgba.A;
+ rgba.G /= rgba.A;
+ rgba.B /= rgba.A;
+ } else {
+ assert(
+ rgba.R === 0.0 && rgba.G === 0.0 && rgba.B === 0.0 && rgba.A === 0.0,
+ 'Unpremultiply ops with alpha value 0.0 requires all channels equals to 0.0'
+ );
+ }
+ }
+ // It's possible RGB are now > 1.
+ // This technically represents colors outside the src gamut, so no clamping yet.
+
+ if (requireColorSpaceConversion) {
+ // WebGPU currently only supports dstColorSpace = 'srgb'.
+ if (srcColorSpace === 'display-p3' && dstColorSpace === 'srgb') {
+ rgba = displayP3ToSrgb(rgba);
+ } else {
+ unreachable();
+ }
+ }
+ // Now RGB may also be negative if the src gamut is larger than the dst gamut.
+
+ if (requirePremultiplyAlpha) {
+ rgba.R *= rgba.A;
+ rgba.G *= rgba.A;
+ rgba.B *= rgba.A;
+ }
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/command_buffer_maker.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/command_buffer_maker.js
new file mode 100644
index 0000000000..b3e0463fb2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/command_buffer_maker.js
@@ -0,0 +1,61 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const kRenderEncodeTypes = ['render pass', 'render bundle'];
+
+export const kProgrammableEncoderTypes = ['compute pass', ...kRenderEncodeTypes];
+
+export const kEncoderTypes = ['non-pass', ...kProgrammableEncoderTypes];
+
+/** See {@link webgpu/api/validation/validation_test.ValidationTest.createEncoder |
+ * GPUTest.createEncoder()}. */
+export class CommandBufferMaker {
+ /** `GPU___Encoder` for recording commands into. */
+ // Look up the type of the encoder based on `T`. If `T` is a union, this will be too!
+
+ /**
+ * Finish any passes, finish and record any bundles, and finish/return the command buffer. Any
+ * errors are ignored and the GPUCommandBuffer (which may be an error buffer) is returned.
+ */
+
+ /**
+ * Finish any passes, finish and record any bundles, and finish/return the command buffer.
+ * Checks for validation errors in (only) the appropriate finish call.
+ */
+
+ /**
+ * Finish the command buffer and submit it. Checks for validation errors in either the submit or
+ * the appropriate finish call, depending on the state of a resource used in the encoding.
+ */
+
+ /**
+ * `validateFinishAndSubmit()` based on the state of a resource in the command encoder.
+ * - `finish()` should fail if the resource is 'invalid'.
+ * - Only `submit()` should fail if the resource is 'destroyed'.
+ */
+
+ constructor(t, encoder, finish) {
+ // TypeScript introduces an intersection type here where we don't want one.
+ this.encoder = encoder;
+ this.finish = finish;
+
+ // Define extra methods like this, otherwise they get unbound when destructured, e.g.:
+ // const { encoder, validateFinishAndSubmit } = t.createEncoder(type);
+ // Alternatively, do not destructure, and call member functions, e.g.:
+ // const encoder = t.createEncoder(type);
+ // encoder.validateFinish(true);
+ this.validateFinish = shouldSucceed => {
+ return t.expectGPUError('validation', this.finish, !shouldSucceed);
+ };
+
+ this.validateFinishAndSubmit = (shouldBeValid, submitShouldSucceedIfValid) => {
+ const commandBuffer = this.validateFinish(shouldBeValid);
+ if (shouldBeValid) {
+ t.expectValidationError(() => t.queue.submit([commandBuffer]), !submitShouldSucceedIfValid);
+ }
+ };
+
+ this.validateFinishAndSubmitGivenState = resourceState => {
+ this.validateFinishAndSubmit(resourceState !== 'invalid', resourceState !== 'destroyed');
+ };
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js
new file mode 100644
index 0000000000..66d0410319
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/compare.js
@@ -0,0 +1,257 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { getIsBuildingDataCache } from '../../common/framework/data_cache.js';
+import { Colors } from '../../common/util/colors.js';
+import {
+ deserializeExpectation,
+ serializeExpectation,
+} from '../shader/execution/expression/case_cache.js';
+import { toComparator } from '../shader/execution/expression/expression.js';
+
+import { isFloatValue, Scalar, Vector } from './conversion.js';
+import { F32Interval } from './f32_interval.js';
+
+/** Comparison describes the result of a Comparator function. */
+
+/**
+ * compares 'got' Value to 'expected' Value, returning the Comparison information.
+ * @param got the Value obtained from the test
+ * @param expected the expected Value
+ * @returns the comparison results
+ */
+function compareValue(got, expected) {
+ {
+ // Check types
+ const gTy = got.type;
+ const eTy = expected.type;
+ const bothFloatTypes = isFloatValue(got) && isFloatValue(expected);
+ if (gTy !== eTy && !bothFloatTypes) {
+ return {
+ matched: false,
+ got: `${Colors.red(gTy.toString())}(${got})`,
+ expected: `${Colors.red(eTy.toString())}(${expected})`,
+ };
+ }
+ }
+
+ if (got instanceof Scalar) {
+ const g = got;
+ const e = expected;
+ const isFloat = g.type.kind === 'f64' || g.type.kind === 'f32' || g.type.kind === 'f16';
+ const matched = (isFloat && g.value === e.value) || (!isFloat && g.value === e.value);
+ return {
+ matched,
+ got: g.toString(),
+ expected: matched ? Colors.green(e.toString()) : Colors.red(e.toString()),
+ };
+ }
+
+ if (got instanceof Vector) {
+ const gLen = got.elements.length;
+ const eLen = expected.elements.length;
+ let matched = gLen === eLen;
+ const gElements = new Array(gLen);
+ const eElements = new Array(eLen);
+ for (let i = 0; i < Math.max(gLen, eLen); i++) {
+ if (i < gLen && i < eLen) {
+ const g = got.elements[i];
+ const e = expected.elements[i];
+ const cmp = compare(g, e);
+ matched = matched && cmp.matched;
+ gElements[i] = cmp.got;
+ eElements[i] = cmp.expected;
+ continue;
+ }
+ matched = false;
+ if (i < gLen) {
+ gElements[i] = got.elements[i].toString();
+ }
+ if (i < eLen) {
+ eElements[i] = expected.elements[i].toString();
+ }
+ }
+ return {
+ matched,
+ got: `${got.type}(${gElements.join(', ')})`,
+ expected: `${expected.type}(${eElements.join(', ')})`,
+ };
+ }
+ throw new Error(`unhandled type '${typeof got}`);
+}
+
+/**
+ * Tests it a 'got' Value is contained in 'expected' interval, returning the Comparison information.
+ * @param got the Value obtained from the test
+ * @param expected the expected F32Interval
+ * @returns the comparison results
+ */
+function compareInterval(got, expected) {
+ {
+ // Check type
+ const gTy = got.type;
+ if (!isFloatValue(got)) {
+ return {
+ matched: false,
+ got: `${Colors.red(gTy.toString())}(${got})`,
+ expected: `floating point value`,
+ };
+ }
+ }
+
+ if (got instanceof Scalar) {
+ const g = got.value;
+ const matched = expected.contains(g);
+ return {
+ matched,
+ got: g.toString(),
+ expected: matched ? Colors.green(expected.toString()) : Colors.red(expected.toString()),
+ };
+ }
+
+ // Vector results are currently not handled
+ throw new Error(`unhandled type '${typeof got}`);
+}
+
+/**
+ * Tests it a 'got' Value is contained in 'expected' vector, returning the Comparison information.
+ * @param got the Value obtained from the test, is expected to be a Vector
+ * @param expected the expected array of F32Intervals, one for each element of the vector
+ * @returns the comparison results
+ */
+function compareVector(got, expected) {
+ // Check got type
+ if (!(got instanceof Vector)) {
+ return {
+ matched: false,
+ got: `${Colors.red((typeof got).toString())}(${got})`,
+ expected: `Vector`,
+ };
+ }
+
+ // Check element type
+ {
+ const gTy = got.type.elementType;
+ if (!isFloatValue(got.elements[0])) {
+ return {
+ matched: false,
+ got: `${Colors.red(gTy.toString())}(${got})`,
+ expected: `floating point elements`,
+ };
+ }
+ }
+
+ if (got.elements.length !== expected.length) {
+ return {
+ matched: false,
+ got: `Vector of ${got.elements.length} elements`,
+ expected: `${expected.length} elements`,
+ };
+ }
+
+ const results = got.elements.map((_, idx) => {
+ const g = got.elements[idx].value;
+ return { match: expected[idx].contains(g), index: idx };
+ });
+
+ const failures = results.filter(v => !v.match).map(v => v.index);
+ if (failures.length !== 0) {
+ const expected_string = expected.map((v, idx) =>
+ idx in failures ? Colors.red(`[${v}]`) : Colors.green(`[${v}]`)
+ );
+
+ return {
+ matched: false,
+ got: `[${got.elements}]`,
+ expected: `[${expected_string}]`,
+ };
+ }
+
+ return {
+ matched: true,
+ got: `[${got.elements}]`,
+ expected: `[${Colors.green(expected.toString())}]`,
+ };
+}
+
+/**
+ * compare() compares 'got' to 'expected', returning the Comparison information.
+ * @param got the result obtained from the test
+ * @param expected the expected result
+ * @returns the comparison results
+ */
+export function compare(got, expected) {
+ if (expected instanceof Array) {
+ return compareVector(got, expected);
+ }
+
+ if (expected instanceof F32Interval) {
+ return compareInterval(got, expected);
+ }
+
+ return compareValue(got, expected);
+}
+
+/** @returns a Comparator that checks whether a test value matches any of the provided options */
+export function anyOf(...expectations) {
+ const comparator = got => {
+ const failed = new Set();
+ for (const e of expectations) {
+ const cmp = toComparator(e)(got);
+ if (cmp.matched) {
+ return cmp;
+ }
+ failed.add(cmp.expected);
+ }
+ return { matched: false, got: got.toString(), expected: [...failed].join(' or ') };
+ };
+
+ if (getIsBuildingDataCache()) {
+ // If there's an active DataCache, and it supports storing, then append the
+ // comparator kind and serialized expectations to the comparator, so it can
+ // be serialized.
+ comparator.kind = 'anyOf';
+ comparator.data = expectations.map(e => serializeExpectation(e));
+ }
+ return comparator;
+}
+
+/** @returns a Comparator that skips the test if the expectation is undefined */
+export function skipUndefined(expectation) {
+ const comparator = got => {
+ if (expectation !== undefined) {
+ return toComparator(expectation)(got);
+ }
+ return { matched: true, got: got.toString(), expected: `Treating 'undefined' as Any` };
+ };
+
+ if (getIsBuildingDataCache()) {
+ // If there's an active DataCache, and it supports storing, then append the
+ // comparator kind and serialized expectations to the comparator, so it can
+ // be serialized.
+ comparator.kind = 'skipUndefined';
+ if (expectation !== undefined) {
+ comparator.data = serializeExpectation(expectation);
+ }
+ }
+ return comparator;
+}
+
+/** SerializedComparatorAnyOf is the serialized type of an `anyOf` comparator. */
+
+/**
+ * Deserializes a comparator from a SerializedComparator.
+ * @param data the SerializedComparator
+ * @returns the deserialized Comparator.
+ */
+export function deserializeComparator(data) {
+ switch (data.kind) {
+ case 'anyOf': {
+ return anyOf(...data.data.map(e => deserializeExpectation(e)));
+ }
+ case 'skipUndefined': {
+ return skipUndefined(data.data !== undefined ? deserializeExpectation(data.data) : undefined);
+ }
+ }
+
+ throw `unhandled comparator kind`;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js
new file mode 100644
index 0000000000..7ac9d75ea5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/constants.js
@@ -0,0 +1,591 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { Float16Array } from '../../external/petamoriken/float16/float16.js'; // MAINTENANCE_TODO(sarahM0): Perhaps instead of kBit and kValue tables we could have one table
+// where every value is a Scalar instead of either bits or value?
+// Then tests wouldn't need most of the Scalar.fromX calls,
+// and you would probably need fewer table entries in total
+// (since each Scalar has both bits and value).
+export const kBit = {
+ // Limits of int32
+ i32: {
+ positive: {
+ min: 0x0000_0000, // 0
+ max: 0x7fff_ffff, // 2147483647
+ },
+ negative: {
+ min: 0x8000_0000, // -2147483648
+ max: 0x0000_0000, // 0
+ },
+ },
+
+ // Limits of uint32
+ u32: {
+ min: 0x0000_0000,
+ max: 0xffff_ffff,
+ },
+
+ // Limits of f32
+ f32: {
+ positive: {
+ min: 0x0080_0000,
+ max: 0x7f7f_ffff,
+ zero: 0x0000_0000,
+ nearest_max: 0x7f7f_fffe,
+ less_than_one: 0x3f7f_ffff,
+ pi: {
+ whole: 0x404_90fdb,
+ three_quarters: 0x4016_cbe4,
+ half: 0x3fc9_0fdb,
+ third: 0x3f86_0a92,
+ quarter: 0x3f49_0fdb,
+ sixth: 0x3f06_0a92,
+ },
+ e: 0x402d_f854,
+ },
+ negative: {
+ max: 0x8080_0000,
+ min: 0xff7f_ffff,
+ zero: 0x8000_0000,
+ nearest_min: 0xff7f_fffe,
+ less_than_one: 0xbf7f_ffff,
+ pi: {
+ whole: 0xc04_90fdb,
+ three_quarters: 0xc016_cbe4,
+ half: 0xbfc90fdb,
+ third: 0xbf860a92,
+ quarter: 0xbf49_0fdb,
+ sixth: 0xbf06_0a92,
+ },
+ },
+ subnormal: {
+ positive: {
+ min: 0x0000_0001,
+ max: 0x007f_ffff,
+ },
+ negative: {
+ max: 0x8000_0001,
+ min: 0x807f_ffff,
+ },
+ },
+ nan: {
+ negative: {
+ s: 0xff80_0001,
+ q: 0xffc0_0001,
+ },
+ positive: {
+ s: 0x7f80_0001,
+ q: 0x7fc0_0001,
+ },
+ },
+ infinity: {
+ positive: 0x7f80_0000,
+ negative: 0xff80_0000,
+ },
+ },
+
+ // Limits of f16
+ f16: {
+ positive: {
+ min: 0x0400,
+ max: 0x7bff,
+ zero: 0x0000,
+ },
+ negative: {
+ max: 0x8400,
+ min: 0xfbff,
+ zero: 0x8000,
+ },
+ subnormal: {
+ positive: {
+ min: 0x0001,
+ max: 0x03ff,
+ },
+ negative: {
+ max: 0x8001,
+ min: 0x83ff,
+ },
+ },
+ nan: {
+ negative: {
+ s: 0xfc01,
+ q: 0xfe01,
+ },
+ positive: {
+ s: 0x7c01,
+ q: 0x7e01,
+ },
+ },
+ infinity: {
+ positive: 0x7c00,
+ negative: 0xfc00,
+ },
+ },
+
+ // 32-bit representation of power(2, n) n = {-31, ..., 31}
+ // A uint32 representation as a JS `number`
+ // {toMinus31, ..., to31} ie. {-31, ..., 31}
+ powTwo: {
+ toMinus1: 0x3f00_0000,
+ toMinus2: 0x3e80_0000,
+ toMinus3: 0x3e00_0000,
+ toMinus4: 0x3d80_0000,
+ toMinus5: 0x3d00_0000,
+ toMinus6: 0x3c80_0000,
+ toMinus7: 0x3c00_0000,
+ toMinus8: 0x3b80_0000,
+ toMinus9: 0x3b00_0000,
+ toMinus10: 0x3a80_0000,
+ toMinus11: 0x3a00_0000,
+ toMinus12: 0x3980_0000,
+ toMinus13: 0x3900_0000,
+ toMinus14: 0x3880_0000,
+ toMinus15: 0x3800_0000,
+ toMinus16: 0x3780_0000,
+ toMinus17: 0x3700_0000,
+ toMinus18: 0x3680_0000,
+ toMinus19: 0x3600_0000,
+ toMinus20: 0x3580_0000,
+ toMinus21: 0x3500_0000,
+ toMinus22: 0x3480_0000,
+ toMinus23: 0x3400_0000,
+ toMinus24: 0x3380_0000,
+ toMinus25: 0x3300_0000,
+ toMinus26: 0x3280_0000,
+ toMinus27: 0x3200_0000,
+ toMinus28: 0x3180_0000,
+ toMinus29: 0x3100_0000,
+ toMinus30: 0x3080_0000,
+ toMinus31: 0x3000_0000,
+
+ to0: 0x0000_0001,
+ to1: 0x0000_0002,
+ to2: 0x0000_0004,
+ to3: 0x0000_0008,
+ to4: 0x0000_0010,
+ to5: 0x0000_0020,
+ to6: 0x0000_0040,
+ to7: 0x0000_0080,
+ to8: 0x0000_0100,
+ to9: 0x0000_0200,
+ to10: 0x0000_0400,
+ to11: 0x0000_0800,
+ to12: 0x0000_1000,
+ to13: 0x0000_2000,
+ to14: 0x0000_4000,
+ to15: 0x0000_8000,
+ to16: 0x0001_0000,
+ to17: 0x0002_0000,
+ to18: 0x0004_0000,
+ to19: 0x0008_0000,
+ to20: 0x0010_0000,
+ to21: 0x0020_0000,
+ to22: 0x0040_0000,
+ to23: 0x0080_0000,
+ to24: 0x0100_0000,
+ to25: 0x0200_0000,
+ to26: 0x0400_0000,
+ to27: 0x0800_0000,
+ to28: 0x1000_0000,
+ to29: 0x2000_0000,
+ to30: 0x4000_0000,
+ to31: 0x8000_0000,
+ },
+
+ // 32-bit representation of of -1 * power(2, n) n = {-31, ..., 31}
+ // An int32 represented as a JS `number`
+ // {toMinus31, ..., to31} ie. {-31, ..., 31}
+ negPowTwo: {
+ toMinus1: 0xbf00_0000,
+ toMinus2: 0xbe80_0000,
+ toMinus3: 0xbe00_0000,
+ toMinus4: 0xbd80_0000,
+ toMinus5: 0xbd00_0000,
+ toMinus6: 0xbc80_0000,
+ toMinus7: 0xbc00_0000,
+ toMinus8: 0xbb80_0000,
+ toMinus9: 0xbb00_0000,
+ toMinus10: 0xba80_0000,
+ toMinus11: 0xba00_0000,
+ toMinus12: 0xb980_0000,
+ toMinus13: 0xb900_0000,
+ toMinus14: 0xb880_0000,
+ toMinus15: 0xb800_0000,
+ toMinus16: 0xb780_0000,
+ toMinus17: 0xb700_0000,
+ toMinus18: 0xb680_0000,
+ toMinus19: 0xb600_0000,
+ toMinus20: 0xb580_0000,
+ toMinus21: 0xb500_0000,
+ toMinus22: 0xb480_0000,
+ toMinus23: 0xb400_0000,
+ toMinus24: 0xb380_0000,
+ toMinus25: 0xb300_0000,
+ toMinus26: 0xb280_0000,
+ toMinus27: 0xb200_0000,
+ toMinus28: 0xb180_0000,
+ toMinus29: 0xb100_0000,
+ toMinus30: 0xb080_0000,
+ toMinus31: 0xb000_0000,
+
+ to0: 0xffff_ffff,
+ to1: 0xffff_fffe,
+ to2: 0xffff_fffc,
+ to3: 0xffff_fff8,
+ to4: 0xffff_fff0,
+ to5: 0xffff_ffe0,
+ to6: 0xffff_ffc0,
+ to7: 0xffff_ff80,
+ to8: 0xffff_ff00,
+ to9: 0xffff_fe00,
+ to10: 0xffff_fc00,
+ to11: 0xffff_f800,
+ to12: 0xffff_f000,
+ to13: 0xffff_e000,
+ to14: 0xffff_c000,
+ to15: 0xffff_8000,
+ to16: 0xffff_0000,
+ to17: 0xfffe_0000,
+ to18: 0xfffc_0000,
+ to19: 0xfff8_0000,
+ to20: 0xfff0_0000,
+ to21: 0xffe0_0000,
+ to22: 0xffc0_0000,
+ to23: 0xff80_0000,
+ to24: 0xff00_0000,
+ to25: 0xfe00_0000,
+ to26: 0xfc00_0000,
+ to27: 0xf800_0000,
+ to28: 0xf000_0000,
+ to29: 0xe000_0000,
+ to30: 0xc000_0000,
+ to31: 0x8000_0000,
+ },
+};
+
+/**
+ * Converts a 64-bit hex value to a 64-bit float value
+ *
+ * Using a locally defined function here to avoid compile time dependency
+ * issues.
+ * */
+function hexToF64(hex) {
+ return new Float64Array(new BigInt64Array([hex]).buffer)[0];
+}
+
+/**
+ * Converts a 64-bit float value to a 64-bit hex value
+ *
+ * Using a locally defined function here to avoid compile time dependency
+ * issues.
+ * */
+function f64ToHex(number) {
+ return new BigUint64Array(new Float64Array([number]).buffer)[0];
+}
+
+/**
+ * Converts a 32-bit hex value to a 32-bit float value
+ *
+ * Using a locally defined function here to avoid compile time dependency
+ * issues.
+ * */
+function hexToF32(hex) {
+ return new Float32Array(new Uint32Array([hex]).buffer)[0];
+}
+
+/**
+ * Converts a 16-bit hex value to a 16-bit float value
+ *
+ * Using a locally defined function here to avoid compile time dependency
+ * issues.
+ * */
+function hexToF16(hex) {
+ return new Float16Array(new Uint16Array([hex]).buffer)[0];
+}
+
+export const kValue = {
+ // Limits of i32
+ i32: {
+ positive: {
+ min: 0,
+ max: 2147483647,
+ },
+ negative: {
+ min: -2147483648,
+ max: 0,
+ },
+ },
+
+ // Limits of u32
+ u32: {
+ min: 0,
+ max: 4294967295,
+ },
+
+ // Limits of f32
+ f32: {
+ positive: {
+ min: hexToF32(kBit.f32.positive.min),
+ max: hexToF32(kBit.f32.positive.max),
+ nearest_max: hexToF32(kBit.f32.positive.nearest_max),
+ less_than_one: hexToF32(kBit.f32.positive.less_than_one),
+ pi: {
+ whole: hexToF32(kBit.f32.positive.pi.whole),
+ three_quarters: hexToF32(kBit.f32.positive.pi.three_quarters),
+ half: hexToF32(kBit.f32.positive.pi.half),
+ third: hexToF32(kBit.f32.positive.pi.third),
+ quarter: hexToF32(kBit.f32.positive.pi.quarter),
+ sixth: hexToF32(kBit.f32.positive.pi.sixth),
+ },
+ e: hexToF32(kBit.f32.positive.e),
+ first_f64_not_castable: hexToF32(kBit.f32.positive.max) / 2 + 2 ** 127, // mid point of 2**128 and largest f32
+ last_f64_castable: hexToF64(
+ f64ToHex(hexToF32(kBit.f32.positive.max) / 2 + 2 ** 127) - BigInt(1)
+ ),
+ // first_f64_not_castable minus one fraction bit of the 64 bit float representation
+ },
+ negative: {
+ max: hexToF32(kBit.f32.negative.max),
+ min: hexToF32(kBit.f32.negative.min),
+ nearest_min: hexToF32(kBit.f32.negative.nearest_min),
+ less_than_one: hexToF32(kBit.f32.negative.less_than_one), // -0.999999940395
+ pi: {
+ whole: hexToF32(kBit.f32.negative.pi.whole),
+ three_quarters: hexToF32(kBit.f32.negative.pi.three_quarters),
+ half: hexToF32(kBit.f32.negative.pi.half),
+ third: hexToF32(kBit.f32.negative.pi.third),
+ quarter: hexToF32(kBit.f32.negative.pi.quarter),
+ sixth: hexToF32(kBit.f32.negative.pi.sixth),
+ },
+ first_f64_not_castable: -(hexToF32(kBit.f32.positive.max) / 2 + 2 ** 127), // mid point of -2**128 and largest f32
+ last_f64_castable: -hexToF64(
+ f64ToHex(hexToF32(kBit.f32.positive.max) / 2 + 2 ** 127) - BigInt(1)
+ ),
+ // first_f64_not_castable minus one fraction bit of the 64 bit float representation
+ },
+ subnormal: {
+ positive: {
+ min: hexToF32(kBit.f32.subnormal.positive.min),
+ max: hexToF32(kBit.f32.subnormal.positive.max),
+ },
+ negative: {
+ max: hexToF32(kBit.f32.subnormal.negative.max),
+ min: hexToF32(kBit.f32.subnormal.negative.min),
+ },
+ },
+ infinity: {
+ positive: hexToF32(kBit.f32.infinity.positive),
+ negative: hexToF32(kBit.f32.infinity.negative),
+ },
+ },
+
+ // Limits of i16
+ i16: {
+ positive: {
+ min: 0,
+ max: 32767,
+ },
+ negative: {
+ min: -32768,
+ max: 0,
+ },
+ },
+
+ // Limits of u16
+ u16: {
+ min: 0,
+ max: 65535,
+ },
+
+ // Limits of f16
+ f16: {
+ positive: {
+ min: hexToF16(kBit.f16.positive.min),
+ max: hexToF16(kBit.f16.positive.max),
+ zero: hexToF16(kBit.f16.positive.zero),
+ first_f64_not_castable: hexToF16(kBit.f16.positive.max) / 2 + 2 ** 16, // mid point of 2**16 and largest f16
+ last_f64_castable: hexToF64(
+ f64ToHex(hexToF16(kBit.f16.positive.max) / 2 + 2 ** 16) - BigInt(1)
+ ),
+ // first_f64_not_castable minus one fraction bit of the 64 bit float representation
+ },
+ negative: {
+ max: hexToF16(kBit.f16.negative.max),
+ min: hexToF16(kBit.f16.negative.min),
+ zero: hexToF16(kBit.f16.negative.zero),
+ first_f64_not_castable: -(hexToF16(kBit.f16.positive.max) / 2 + 2 ** 16), // mid point of -2**16 and largest f16
+ last_f64_castable: -hexToF64(
+ f64ToHex(hexToF16(kBit.f16.positive.max) / 2 + 2 ** 16) - BigInt(1)
+ ),
+ // first_f64_not_castable minus one fraction bit of the 64 bit float representation
+ },
+ subnormal: {
+ positive: {
+ min: hexToF16(kBit.f16.subnormal.positive.min),
+ max: hexToF16(kBit.f16.subnormal.positive.max),
+ },
+ negative: {
+ max: hexToF16(kBit.f16.subnormal.negative.max),
+ min: hexToF16(kBit.f16.subnormal.negative.min),
+ },
+ },
+ infinity: {
+ positive: hexToF16(kBit.f16.infinity.positive),
+ negative: hexToF16(kBit.f16.infinity.negative),
+ },
+ },
+
+ powTwo: {
+ to0: Math.pow(2, 0),
+ to1: Math.pow(2, 1),
+ to2: Math.pow(2, 2),
+ to3: Math.pow(2, 3),
+ to4: Math.pow(2, 4),
+ to5: Math.pow(2, 5),
+ to6: Math.pow(2, 6),
+ to7: Math.pow(2, 7),
+ to8: Math.pow(2, 8),
+ to9: Math.pow(2, 9),
+ to10: Math.pow(2, 10),
+ to11: Math.pow(2, 11),
+ to12: Math.pow(2, 12),
+ to13: Math.pow(2, 13),
+ to14: Math.pow(2, 14),
+ to15: Math.pow(2, 15),
+ to16: Math.pow(2, 16),
+ to17: Math.pow(2, 17),
+ to18: Math.pow(2, 18),
+ to19: Math.pow(2, 19),
+ to20: Math.pow(2, 20),
+ to21: Math.pow(2, 21),
+ to22: Math.pow(2, 22),
+ to23: Math.pow(2, 23),
+ to24: Math.pow(2, 24),
+ to25: Math.pow(2, 25),
+ to26: Math.pow(2, 26),
+ to27: Math.pow(2, 27),
+ to28: Math.pow(2, 28),
+ to29: Math.pow(2, 29),
+ to30: Math.pow(2, 30),
+ to31: Math.pow(2, 31),
+ to32: Math.pow(2, 32),
+
+ toMinus1: Math.pow(2, -1),
+ toMinus2: Math.pow(2, -2),
+ toMinus3: Math.pow(2, -3),
+ toMinus4: Math.pow(2, -4),
+ toMinus5: Math.pow(2, -5),
+ toMinus6: Math.pow(2, -6),
+ toMinus7: Math.pow(2, -7),
+ toMinus8: Math.pow(2, -8),
+ toMinus9: Math.pow(2, -9),
+ toMinus10: Math.pow(2, -10),
+ toMinus11: Math.pow(2, -11),
+ toMinus12: Math.pow(2, -12),
+ toMinus13: Math.pow(2, -13),
+ toMinus14: Math.pow(2, -14),
+ toMinus15: Math.pow(2, -15),
+ toMinus16: Math.pow(2, -16),
+ toMinus17: Math.pow(2, -17),
+ toMinus18: Math.pow(2, -18),
+ toMinus19: Math.pow(2, -19),
+ toMinus20: Math.pow(2, -20),
+ toMinus21: Math.pow(2, -21),
+ toMinus22: Math.pow(2, -22),
+ toMinus23: Math.pow(2, -23),
+ toMinus24: Math.pow(2, -24),
+ toMinus25: Math.pow(2, -25),
+ toMinus26: Math.pow(2, -26),
+ toMinus27: Math.pow(2, -27),
+ toMinus28: Math.pow(2, -28),
+ toMinus29: Math.pow(2, -29),
+ toMinus30: Math.pow(2, -30),
+ toMinus31: Math.pow(2, -31),
+ toMinus32: Math.pow(2, -32),
+ },
+ negPowTwo: {
+ to0: -Math.pow(2, 0),
+ to1: -Math.pow(2, 1),
+ to2: -Math.pow(2, 2),
+ to3: -Math.pow(2, 3),
+ to4: -Math.pow(2, 4),
+ to5: -Math.pow(2, 5),
+ to6: -Math.pow(2, 6),
+ to7: -Math.pow(2, 7),
+ to8: -Math.pow(2, 8),
+ to9: -Math.pow(2, 9),
+ to10: -Math.pow(2, 10),
+ to11: -Math.pow(2, 11),
+ to12: -Math.pow(2, 12),
+ to13: -Math.pow(2, 13),
+ to14: -Math.pow(2, 14),
+ to15: -Math.pow(2, 15),
+ to16: -Math.pow(2, 16),
+ to17: -Math.pow(2, 17),
+ to18: -Math.pow(2, 18),
+ to19: -Math.pow(2, 19),
+ to20: -Math.pow(2, 20),
+ to21: -Math.pow(2, 21),
+ to22: -Math.pow(2, 22),
+ to23: -Math.pow(2, 23),
+ to24: -Math.pow(2, 24),
+ to25: -Math.pow(2, 25),
+ to26: -Math.pow(2, 26),
+ to27: -Math.pow(2, 27),
+ to28: -Math.pow(2, 28),
+ to29: -Math.pow(2, 29),
+ to30: -Math.pow(2, 30),
+ to31: -Math.pow(2, 31),
+ to32: -Math.pow(2, 32),
+
+ toMinus1: -Math.pow(2, -1),
+ toMinus2: -Math.pow(2, -2),
+ toMinus3: -Math.pow(2, -3),
+ toMinus4: -Math.pow(2, -4),
+ toMinus5: -Math.pow(2, -5),
+ toMinus6: -Math.pow(2, -6),
+ toMinus7: -Math.pow(2, -7),
+ toMinus8: -Math.pow(2, -8),
+ toMinus9: -Math.pow(2, -9),
+ toMinus10: -Math.pow(2, -10),
+ toMinus11: -Math.pow(2, -11),
+ toMinus12: -Math.pow(2, -12),
+ toMinus13: -Math.pow(2, -13),
+ toMinus14: -Math.pow(2, -14),
+ toMinus15: -Math.pow(2, -15),
+ toMinus16: -Math.pow(2, -16),
+ toMinus17: -Math.pow(2, -17),
+ toMinus18: -Math.pow(2, -18),
+ toMinus19: -Math.pow(2, -19),
+ toMinus20: -Math.pow(2, -20),
+ toMinus21: -Math.pow(2, -21),
+ toMinus22: -Math.pow(2, -22),
+ toMinus23: -Math.pow(2, -23),
+ toMinus24: -Math.pow(2, -24),
+ toMinus25: -Math.pow(2, -25),
+ toMinus26: -Math.pow(2, -26),
+ toMinus27: -Math.pow(2, -27),
+ toMinus28: -Math.pow(2, -28),
+ toMinus29: -Math.pow(2, -29),
+ toMinus30: -Math.pow(2, -30),
+ toMinus31: -Math.pow(2, -31),
+ toMinus32: -Math.pow(2, -32),
+ },
+
+ // Limits of i8
+ i8: {
+ positive: {
+ min: 0,
+ max: 127,
+ },
+ negative: {
+ min: -128,
+ max: 0,
+ },
+ },
+
+ // Limits of u8
+ u8: {
+ min: 0,
+ max: 255,
+ },
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js
new file mode 100644
index 0000000000..0120b4665c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/conversion.js
@@ -0,0 +1,1049 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { Colors } from '../../common/util/colors.js';
+import { assert, unreachable } from '../../common/util/util.js';
+import { Float16Array } from '../../external/petamoriken/float16/float16.js';
+
+import { kBit } from './constants.js';
+import {
+ cartesianProduct,
+ clamp,
+ correctlyRoundedF16,
+ isFiniteF16,
+ isSubnormalNumberF16,
+ isSubnormalNumberF32,
+} from './math.js';
+
+/**
+ * Encodes a JS `number` into a "normalized" (unorm/snorm) integer representation with `bits` bits.
+ * Input must be between -1 and 1 if signed, or 0 and 1 if unsigned.
+ *
+ * MAINTENANCE_TODO: See if performance of texel_data improves if this function is pre-specialized
+ * for a particular `bits`/`signed`.
+ */
+export function floatAsNormalizedInteger(float, bits, signed) {
+ if (signed) {
+ assert(float >= -1 && float <= 1, () => `${float} out of bounds of snorm`);
+ const max = Math.pow(2, bits - 1) - 1;
+ return Math.round(float * max);
+ } else {
+ assert(float >= 0 && float <= 1, () => `${float} out of bounds of unorm`);
+ const max = Math.pow(2, bits) - 1;
+ return Math.round(float * max);
+ }
+}
+
+/**
+ * Decodes a JS `number` from a "normalized" (unorm/snorm) integer representation with `bits` bits.
+ * Input must be an integer in the range of the specified unorm/snorm type.
+ */
+export function normalizedIntegerAsFloat(integer, bits, signed) {
+ assert(Number.isInteger(integer));
+ if (signed) {
+ const max = Math.pow(2, bits - 1) - 1;
+ assert(integer >= -max - 1 && integer <= max);
+ if (integer === -max - 1) {
+ integer = -max;
+ }
+ return integer / max;
+ } else {
+ const max = Math.pow(2, bits) - 1;
+ assert(integer >= 0 && integer <= max);
+ return integer / max;
+ }
+}
+
+/**
+ * Encodes a JS `number` into an IEEE754 floating point number with the specified number of
+ * sign, exponent, mantissa bits, and exponent bias.
+ * Returns the result as an integer-valued JS `number`.
+ *
+ * Does not handle clamping, overflow, or denormal inputs.
+ * On underflow (result is subnormal), rounds to (signed) zero.
+ *
+ * MAINTENANCE_TODO: Replace usages of this with numberToFloatBits.
+ */
+export function float32ToFloatBits(n, signBits, exponentBits, mantissaBits, bias) {
+ assert(exponentBits <= 8);
+ assert(mantissaBits <= 23);
+ assert(Number.isFinite(n));
+
+ if (n === 0) {
+ return 0;
+ }
+
+ if (signBits === 0) {
+ assert(n >= 0);
+ }
+
+ const buf = new DataView(new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT));
+ buf.setFloat32(0, n, true);
+ const bits = buf.getUint32(0, true);
+ // bits (32): seeeeeeeefffffffffffffffffffffff
+
+ const mantissaBitsToDiscard = 23 - mantissaBits;
+
+ // 0 or 1
+ const sign = (bits >> 31) & signBits;
+
+ // >> to remove mantissa, & to remove sign, - 127 to remove bias.
+ const exp = ((bits >> 23) & 0xff) - 127;
+
+ // Convert to the new biased exponent.
+ const newBiasedExp = bias + exp;
+ assert(newBiasedExp < 1 << exponentBits, () => `input number ${n} overflows target type`);
+
+ if (newBiasedExp <= 0) {
+ // Result is subnormal or zero. Round to (signed) zero.
+ return sign << (exponentBits + mantissaBits);
+ } else {
+ // Mask only the mantissa, and discard the lower bits.
+ const newMantissa = (bits & 0x7fffff) >> mantissaBitsToDiscard;
+ return (sign << (exponentBits + mantissaBits)) | (newBiasedExp << mantissaBits) | newMantissa;
+ }
+}
+
+/**
+ * Encodes a JS `number` into an IEEE754 16 bit floating point number.
+ * Returns the result as an integer-valued JS `number`.
+ *
+ * Does not handle clamping, overflow, or denormal inputs.
+ * On underflow (result is subnormal), rounds to (signed) zero.
+ */
+export function float32ToFloat16Bits(n) {
+ return float32ToFloatBits(n, 1, 5, 10, 15);
+}
+
+/**
+ * Decodes an IEEE754 16 bit floating point number into a JS `number` and returns.
+ */
+export function float16BitsToFloat32(float16Bits) {
+ return floatBitsToNumber(float16Bits, kFloat16Format);
+}
+
+/** FloatFormat defining IEEE754 32-bit float. */
+export const kFloat32Format = { signed: 1, exponentBits: 8, mantissaBits: 23, bias: 127 };
+/** FloatFormat defining IEEE754 16-bit float. */
+export const kFloat16Format = { signed: 1, exponentBits: 5, mantissaBits: 10, bias: 15 };
+
+/**
+ * Once-allocated ArrayBuffer/views to avoid overhead of allocation when converting between numeric formats
+ *
+ * workingData* is shared between multiple functions in this file, so to avoid re-entrancy problems, make sure in
+ * functions that use it that they don't call themselves or other functions that use workingData*.
+ */
+const workingData = new ArrayBuffer(4);
+const workingDataU32 = new Uint32Array(workingData);
+const workingDataU16 = new Uint16Array(workingData);
+const workingDataU8 = new Uint8Array(workingData);
+const workingDataF32 = new Float32Array(workingData);
+const workingDataF16 = new Float16Array(workingData);
+const workingDataI16 = new Int16Array(workingData);
+const workingDataI8 = new Int8Array(workingData);
+
+/** Bitcast u32 (represented as integer Number) to f32 (represented as floating-point Number). */
+export function float32BitsToNumber(bits) {
+ workingDataU32[0] = bits;
+ return workingDataF32[0];
+}
+/** Bitcast f32 (represented as floating-point Number) to u32 (represented as integer Number). */
+export function numberToFloat32Bits(number) {
+ workingDataF32[0] = number;
+ return workingDataU32[0];
+}
+
+/**
+ * Decodes an IEEE754 float with the supplied format specification into a JS number.
+ *
+ * The format MUST be no larger than a 32-bit float.
+ */
+export function floatBitsToNumber(bits, fmt) {
+ // Pad the provided bits out to f32, then convert to a `number` with the wrong bias.
+ // E.g. for f16 to f32:
+ // - f16: S EEEEE MMMMMMMMMM
+ // ^ 000^^^^^ ^^^^^^^^^^0000000000000
+ // - f32: S eeeEEEEE MMMMMMMMMMmmmmmmmmmmmmm
+
+ const kNonSignBits = fmt.exponentBits + fmt.mantissaBits;
+ const kNonSignBitsMask = (1 << kNonSignBits) - 1;
+ const expAndMantBits = bits & kNonSignBitsMask;
+ let f32BitsWithWrongBias = expAndMantBits << (kFloat32Format.mantissaBits - fmt.mantissaBits);
+ f32BitsWithWrongBias |= (bits << (31 - kNonSignBits)) & 0x8000_0000;
+ const numberWithWrongBias = float32BitsToNumber(f32BitsWithWrongBias);
+ return numberWithWrongBias * 2 ** (kFloat32Format.bias - fmt.bias);
+}
+
+/**
+ * Encodes a JS `number` into an IEEE754 floating point number with the specified format.
+ * Returns the result as an integer-valued JS `number`.
+ *
+ * Does not handle clamping, overflow, or denormal inputs.
+ * On underflow (result is subnormal), rounds to (signed) zero.
+ */
+export function numberToFloatBits(number, fmt) {
+ return float32ToFloatBits(number, fmt.signed, fmt.exponentBits, fmt.mantissaBits, fmt.bias);
+}
+
+/**
+ * Given a floating point number (as an integer representing its bits), computes how many ULPs it is
+ * from zero.
+ *
+ * Subnormal numbers are skipped, so that 0 is one ULP from the minimum normal number.
+ * Subnormal values are flushed to 0.
+ * Positive and negative 0 are both considered to be 0 ULPs from 0.
+ */
+export function floatBitsToNormalULPFromZero(bits, fmt) {
+ const mask_sign = fmt.signed << (fmt.exponentBits + fmt.mantissaBits);
+ const mask_expt = ((1 << fmt.exponentBits) - 1) << fmt.mantissaBits;
+ const mask_mant = (1 << fmt.mantissaBits) - 1;
+ const mask_rest = mask_expt | mask_mant;
+
+ assert(fmt.exponentBits + fmt.mantissaBits <= 31);
+
+ const sign = bits & mask_sign ? -1 : 1;
+ const rest = bits & mask_rest;
+ const subnormal_or_zero = (bits & mask_expt) === 0;
+ const infinity_or_nan = (bits & mask_expt) === mask_expt;
+ assert(!infinity_or_nan, 'no ulp representation for infinity/nan');
+
+ // The first normal number is mask_mant+1, so subtract mask_mant to make min_normal - zero = 1ULP.
+ const abs_ulp_from_zero = subnormal_or_zero ? 0 : rest - mask_mant;
+ return sign * abs_ulp_from_zero;
+}
+
+/**
+ * Encodes three JS `number` values into RGB9E5, returned as an integer-valued JS `number`.
+ *
+ * RGB9E5 represents three partial-precision floating-point numbers encoded into a single 32-bit
+ * value all sharing the same 5-bit exponent.
+ * There is no sign bit, and there is a shared 5-bit biased (15) exponent and a 9-bit
+ * mantissa for each channel. The mantissa does NOT have an implicit leading "1.",
+ * and instead has an implicit leading "0.".
+ */
+export function packRGB9E5UFloat(r, g, b) {
+ for (const v of [r, g, b]) {
+ assert(v >= 0 && v < Math.pow(2, 16));
+ }
+
+ const buf = new DataView(new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT));
+ const extractMantissaAndExponent = n => {
+ const mantissaBits = 9;
+ buf.setFloat32(0, n, true);
+ const bits = buf.getUint32(0, true);
+ // >> to remove mantissa, & to remove sign
+ let biasedExponent = (bits >> 23) & 0xff;
+ const mantissaBitsToDiscard = 23 - mantissaBits;
+ let mantissa = (bits & 0x7fffff) >> mantissaBitsToDiscard;
+
+ // RGB9E5UFloat has an implicit leading 0. instead of a leading 1.,
+ // so we need to move the 1. into the mantissa and bump the exponent.
+ // For float32 encoding, the leading 1 is only present if the biased
+ // exponent is non-zero.
+ if (biasedExponent !== 0) {
+ mantissa = (mantissa >> 1) | 0b100000000;
+ biasedExponent += 1;
+ }
+ return { biasedExponent, mantissa };
+ };
+
+ const { biasedExponent: rExp, mantissa: rOrigMantissa } = extractMantissaAndExponent(r);
+ const { biasedExponent: gExp, mantissa: gOrigMantissa } = extractMantissaAndExponent(g);
+ const { biasedExponent: bExp, mantissa: bOrigMantissa } = extractMantissaAndExponent(b);
+
+ // Use the largest exponent, and shift the mantissa accordingly
+ const exp = Math.max(rExp, gExp, bExp);
+ const rMantissa = rOrigMantissa >> (exp - rExp);
+ const gMantissa = gOrigMantissa >> (exp - gExp);
+ const bMantissa = bOrigMantissa >> (exp - bExp);
+
+ const bias = 15;
+ const biasedExp = exp === 0 ? 0 : exp - 127 + bias;
+ assert(biasedExp >= 0 && biasedExp <= 31);
+ return rMantissa | (gMantissa << 9) | (bMantissa << 18) | (biasedExp << 27);
+}
+
+/**
+ * Quantizes two f32s to f16 and then packs them in a u32
+ *
+ * This should implement the same behaviour as the builtin `pack2x16float` from
+ * WGSL.
+ *
+ * Caller is responsible to ensuring inputs are f32s
+ *
+ * @param x first f32 to be packed
+ * @param y second f32 to be packed
+ * @returns an array of possible results for pack2x16float. Elements are either
+ * a number or undefined.
+ * undefined indicates that any value is valid, since the input went
+ * out of bounds.
+ */
+export function pack2x16float(x, y) {
+ // Generates all possible valid u16 bit fields for a given f32 to f16 conversion.
+ // Assumes FTZ for both the f32 and f16 value is allowed.
+ const generateU16s = n => {
+ let contains_subnormals = isSubnormalNumberF32(n);
+ const n_f16s = correctlyRoundedF16(n);
+ contains_subnormals ||= n_f16s.some(isSubnormalNumberF16);
+
+ const n_u16s = n_f16s.map(f16 => {
+ workingDataF16[0] = f16;
+ return workingDataU16[0];
+ });
+
+ const contains_poszero = n_u16s.some(u => u === kBit.f16.positive.zero);
+ const contains_negzero = n_u16s.some(u => u === kBit.f16.negative.zero);
+ if (!contains_negzero && (contains_poszero || contains_subnormals)) {
+ n_u16s.push(kBit.f16.negative.zero);
+ }
+
+ if (!contains_poszero && (contains_negzero || contains_subnormals)) {
+ n_u16s.push(kBit.f16.positive.zero);
+ }
+
+ return n_u16s;
+ };
+
+ if (!isFiniteF16(x) || !isFiniteF16(y)) {
+ // This indicates any value is valid, so it isn't worth bothering
+ // calculating the more restrictive possibilities.
+ return [undefined];
+ }
+
+ const results = new Array();
+ for (const p of cartesianProduct(generateU16s(x), generateU16s(y))) {
+ assert(p.length === 2, 'cartesianProduct of 2 arrays returned an entry with not 2 elements');
+ workingDataU16[0] = p[0];
+ workingDataU16[1] = p[1];
+ results.push(workingDataU32[0]);
+ }
+
+ return results;
+}
+
+/**
+ * Converts two normalized f32s to i16s and then packs them in a u32
+ *
+ * This should implement the same behaviour as the builtin `pack2x16snorm` from
+ * WGSL.
+ *
+ * Caller is responsible to ensuring inputs are normalized f32s
+ *
+ * @param x first f32 to be packed
+ * @param y second f32 to be packed
+ * @returns a number that is expected result of pack2x16snorm.
+ */
+export function pack2x16snorm(x, y) {
+ // Converts f32 to i16 via the pack2x16snorm formula.
+ // FTZ is not explicitly handled, because all subnormals will produce a value
+ // between 0 and 1, but significantly away from the edges, so floor goes to 0.
+ const generateI16 = n => {
+ return Math.floor(0.5 + 32767 * Math.min(1, Math.max(-1, n)));
+ };
+
+ workingDataI16[0] = generateI16(x);
+ workingDataI16[1] = generateI16(y);
+
+ return workingDataU32[0];
+}
+
+/**
+ * Converts two normalized f32s to u16s and then packs them in a u32
+ *
+ * This should implement the same behaviour as the builtin `pack2x16unorm` from
+ * WGSL.
+ *
+ * Caller is responsible to ensuring inputs are normalized f32s
+ *
+ * @param x first f32 to be packed
+ * @param y second f32 to be packed
+ * @returns an number that is expected result of pack2x16unorm.
+ */
+export function pack2x16unorm(x, y) {
+ // Converts f32 to u16 via the pack2x16unorm formula.
+ // FTZ is not explicitly handled, because all subnormals will produce a value
+ // between 0.5 and much less than 1, so floor goes to 0.
+ const generateU16 = n => {
+ return Math.floor(0.5 + 65535 * Math.min(1, Math.max(0, n)));
+ };
+
+ workingDataU16[0] = generateU16(x);
+ workingDataU16[1] = generateU16(y);
+
+ return workingDataU32[0];
+}
+
+/**
+ * Converts four normalized f32s to i8s and then packs them in a u32
+ *
+ * This should implement the same behaviour as the builtin `pack4x8snorm` from
+ * WGSL.
+ *
+ * Caller is responsible to ensuring inputs are normalized f32s
+ *
+ * @param vals four f32s to be packed
+ * @returns a number that is expected result of pack4x8usorm.
+ */
+export function pack4x8snorm(...vals) {
+ // Converts f32 to u8 via the pack4x8snorm formula.
+ // FTZ is not explicitly handled, because all subnormals will produce a value
+ // between 0 and 1, so floor goes to 0.
+ const generateI8 = n => {
+ return Math.floor(0.5 + 127 * Math.min(1, Math.max(-1, n)));
+ };
+
+ for (const idx in vals) {
+ workingDataI8[idx] = generateI8(vals[idx]);
+ }
+
+ return workingDataU32[0];
+}
+
+/**
+ * Converts four normalized f32s to u8s and then packs them in a u32
+ *
+ * This should implement the same behaviour as the builtin `pack4x8unorm` from
+ * WGSL.
+ *
+ * Caller is responsible to ensuring inputs are normalized f32s
+ *
+ * @param vals four f32s to be packed
+ * @returns a number that is expected result of pack4x8unorm.
+ */
+export function pack4x8unorm(...vals) {
+ // Converts f32 to u8 via the pack4x8unorm formula.
+ // FTZ is not explicitly handled, because all subnormals will produce a value
+ // between 0.5 and much less than 1, so floor goes to 0.
+ const generateU8 = n => {
+ return Math.floor(0.5 + 255 * Math.min(1, Math.max(0, n)));
+ };
+
+ for (const idx in vals) {
+ workingDataU8[idx] = generateU8(vals[idx]);
+ }
+
+ return workingDataU32[0];
+}
+
+/**
+ * Asserts that a number is within the representable (inclusive) of the integer type with the
+ * specified number of bits and signedness.
+ *
+ * MAINTENANCE_TODO: Assert isInteger? Then this function "asserts that a number is representable"
+ * by the type.
+ */
+export function assertInIntegerRange(n, bits, signed) {
+ if (signed) {
+ const min = -Math.pow(2, bits - 1);
+ const max = Math.pow(2, bits - 1) - 1;
+ assert(n >= min && n <= max);
+ } else {
+ const max = Math.pow(2, bits) - 1;
+ assert(n >= 0 && n <= max);
+ }
+}
+
+/**
+ * Converts a linear value into a "gamma"-encoded value using the sRGB-clamped transfer function.
+ */
+export function gammaCompress(n) {
+ n = n <= 0.0031308 ? (323 * n) / 25 : (211 * Math.pow(n, 5 / 12) - 11) / 200;
+ return clamp(n, { min: 0, max: 1 });
+}
+
+/**
+ * Converts a "gamma"-encoded value into a linear value using the sRGB-clamped transfer function.
+ */
+export function gammaDecompress(n) {
+ n = n <= 0.04045 ? (n * 25) / 323 : Math.pow((200 * n + 11) / 211, 12 / 5);
+ return clamp(n, { min: 0, max: 1 });
+}
+
+/** Converts a 32-bit float value to a 32-bit unsigned integer value */
+export function float32ToUint32(f32) {
+ const f32Arr = new Float32Array(1);
+ f32Arr[0] = f32;
+ const u32Arr = new Uint32Array(f32Arr.buffer);
+ return u32Arr[0];
+}
+
+/** Converts a 32-bit unsigned integer value to a 32-bit float value */
+export function uint32ToFloat32(u32) {
+ const u32Arr = new Uint32Array(1);
+ u32Arr[0] = u32;
+ const f32Arr = new Float32Array(u32Arr.buffer);
+ return f32Arr[0];
+}
+
+/** Converts a 32-bit float value to a 32-bit signed integer value */
+export function float32ToInt32(f32) {
+ const f32Arr = new Float32Array(1);
+ f32Arr[0] = f32;
+ const i32Arr = new Int32Array(f32Arr.buffer);
+ return i32Arr[0];
+}
+
+/** Converts a 32-bit unsigned integer value to a 32-bit signed integer value */
+export function uint32ToInt32(u32) {
+ const u32Arr = new Uint32Array(1);
+ u32Arr[0] = u32;
+ const i32Arr = new Int32Array(u32Arr.buffer);
+ return i32Arr[0];
+}
+
+/** Converts a 16-bit float value to a 16-bit unsigned integer value */
+export function float16ToUint16(f16) {
+ const f16Arr = new Float16Array(1);
+ f16Arr[0] = f16;
+ const u16Arr = new Uint16Array(f16Arr.buffer);
+ return u16Arr[0];
+}
+
+/** Converts a 16-bit unsigned integer value to a 16-bit float value */
+export function uint16ToFloat16(u16) {
+ const u16Arr = new Uint16Array(1);
+ u16Arr[0] = u16;
+ const f16Arr = new Float16Array(u16Arr.buffer);
+ return f16Arr[0];
+}
+
+/** Converts a 16-bit float value to a 16-bit signed integer value */
+export function float16ToInt16(f16) {
+ const f16Arr = new Float16Array(1);
+ f16Arr[0] = f16;
+ const i16Arr = new Int16Array(f16Arr.buffer);
+ return i16Arr[0];
+}
+
+/** A type of number representable by Scalar. */
+
+/** ScalarType describes the type of WGSL Scalar. */
+export class ScalarType {
+ // The named type
+ // In bytes
+ // reads a scalar from a buffer
+
+ constructor(kind, size, read) {
+ this.kind = kind;
+ this._size = size;
+ this.read = read;
+ }
+
+ toString() {
+ return this.kind;
+ }
+
+ get size() {
+ return this._size;
+ }
+}
+
+/** ScalarType describes the type of WGSL Vector. */
+export class VectorType {
+ // Number of elements in the vector
+ // Element type
+
+ constructor(width, elementType) {
+ this.width = width;
+ this.elementType = elementType;
+ }
+
+ /**
+ * @returns a vector constructed from the values read from the buffer at the
+ * given byte offset
+ */
+ read(buf, offset) {
+ const elements = [];
+ for (let i = 0; i < this.width; i++) {
+ elements[i] = this.elementType.read(buf, offset);
+ offset += this.elementType.size;
+ }
+ return new Vector(elements);
+ }
+
+ toString() {
+ return `vec${this.width}<${this.elementType}>`;
+ }
+
+ get size() {
+ return this.elementType.size * this.width;
+ }
+}
+
+// Maps a string representation of a vector type to vector type.
+const vectorTypes = new Map();
+
+export function TypeVec(width, elementType) {
+ const key = `${elementType.toString()} ${width}}`;
+ let ty = vectorTypes.get(key);
+ if (ty !== undefined) {
+ return ty;
+ }
+ ty = new VectorType(width, elementType);
+ vectorTypes.set(key, ty);
+ return ty;
+}
+
+/** Type is a ScalarType or VectorType. */
+
+export const TypeI32 = new ScalarType('i32', 4, (buf, offset) =>
+ i32(new Int32Array(buf.buffer, offset)[0])
+);
+
+export const TypeU32 = new ScalarType('u32', 4, (buf, offset) =>
+ u32(new Uint32Array(buf.buffer, offset)[0])
+);
+
+export const TypeF64 = new ScalarType('f64', 8, (buf, offset) =>
+ f32(new Float64Array(buf.buffer, offset)[0])
+);
+
+export const TypeF32 = new ScalarType('f32', 4, (buf, offset) =>
+ f32(new Float32Array(buf.buffer, offset)[0])
+);
+
+export const TypeI16 = new ScalarType('i16', 2, (buf, offset) =>
+ i16(new Int16Array(buf.buffer, offset)[0])
+);
+
+export const TypeU16 = new ScalarType('u16', 2, (buf, offset) =>
+ u16(new Uint16Array(buf.buffer, offset)[0])
+);
+
+export const TypeF16 = new ScalarType('f16', 2, (buf, offset) =>
+ f16Bits(new Uint16Array(buf.buffer, offset)[0])
+);
+
+export const TypeI8 = new ScalarType('i8', 1, (buf, offset) =>
+ i8(new Int8Array(buf.buffer, offset)[0])
+);
+
+export const TypeU8 = new ScalarType('u8', 1, (buf, offset) =>
+ u8(new Uint8Array(buf.buffer, offset)[0])
+);
+
+export const TypeBool = new ScalarType('bool', 4, (buf, offset) =>
+ bool(new Uint32Array(buf.buffer, offset)[0] !== 0)
+);
+
+/** @returns the ScalarType from the ScalarKind */
+export function scalarType(kind) {
+ switch (kind) {
+ case 'f64':
+ return TypeF64;
+ case 'f32':
+ return TypeF32;
+ case 'f16':
+ return TypeF16;
+ case 'u32':
+ return TypeU32;
+ case 'u16':
+ return TypeU16;
+ case 'u8':
+ return TypeU8;
+ case 'i32':
+ return TypeI32;
+ case 'i16':
+ return TypeI16;
+ case 'i8':
+ return TypeI8;
+ case 'bool':
+ return TypeBool;
+ }
+}
+
+/** @returns the number of scalar (element) types of the given Type */
+export function numElementsOf(ty) {
+ if (ty instanceof ScalarType) {
+ return 1;
+ }
+ if (ty instanceof VectorType) {
+ return ty.width;
+ }
+ throw new Error(`unhandled type ${ty}`);
+}
+
+/** @returns the scalar (element) type of the given Type */
+export function scalarTypeOf(ty) {
+ if (ty instanceof ScalarType) {
+ return ty;
+ }
+ if (ty instanceof VectorType) {
+ return ty.elementType;
+ }
+ throw new Error(`unhandled type ${ty}`);
+}
+
+/** ScalarValue is the JS type that can be held by a Scalar */
+
+/** Class that encapsulates a single scalar value of various types. */
+export class Scalar {
+ // The scalar value
+ // The type of the scalar
+ // The scalar value packed in a Uint8Array
+
+ constructor(type, value, bits) {
+ this.value = value;
+ this.type = type;
+ this.bits = new Uint8Array(bits.buffer);
+ }
+
+ /**
+ * Copies the scalar value to the Uint8Array buffer at the provided byte offset.
+ * @param buffer the destination buffer
+ * @param offset the byte offset within buffer
+ */
+ copyTo(buffer, offset) {
+ for (let i = 0; i < this.bits.length; i++) {
+ buffer[offset + i] = this.bits[i];
+ }
+ }
+
+ /**
+ * @returns the WGSL representation of this scalar value
+ */
+ wgsl() {
+ const withPoint = x => {
+ const str = `${x}`;
+ return str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`;
+ };
+ if (isFinite(this.value)) {
+ switch (this.type.kind) {
+ case 'f32':
+ return `${withPoint(this.value)}f`;
+ case 'f16':
+ return `${withPoint(this.value)}h`;
+ case 'u32':
+ return `${this.value}u`;
+ case 'i32':
+ return `i32(${this.value})`;
+ case 'bool':
+ return `${this.value}`;
+ }
+ }
+ throw new Error(
+ `scalar of value ${this.value} and type ${this.type} has no WGSL representation`
+ );
+ }
+
+ toString() {
+ if (this.type.kind === 'bool') {
+ return Colors.bold(this.value.toString());
+ }
+ switch (this.value) {
+ case Infinity:
+ case -Infinity:
+ return Colors.bold(this.value.toString());
+ default: {
+ // Uint8Array.map returns a Uint8Array, so cannot use .map directly
+ const hex = Array.from(this.bits)
+ .reverse()
+ .map(x => x.toString(16).padStart(2, '0'))
+ .join('');
+ const n = this.value;
+ if (n !== null && isFloatValue(this)) {
+ let str = this.value.toString();
+ str = str.indexOf('.') > 0 || str.indexOf('e') > 0 ? str : `${str}.0`;
+ return isSubnormalNumberF32(n.valueOf())
+ ? `${Colors.bold(str)} (0x${hex} subnormal)`
+ : `${Colors.bold(str)} (0x${hex})`;
+ }
+ return `${Colors.bold(this.value.toString())} (0x${hex})`;
+ }
+ }
+ }
+}
+
+/** Create an f64 from a numeric value, a JS `number`. */
+export function f64(value) {
+ const arr = new Float64Array([value]);
+ return new Scalar(TypeF64, arr[0], arr);
+}
+/** Create an f32 from a numeric value, a JS `number`. */
+export function f32(value) {
+ const arr = new Float32Array([value]);
+ return new Scalar(TypeF32, arr[0], arr);
+}
+/** Create an f16 from a numeric value, a JS `number`. */
+export function f16(value) {
+ const arr = new Float16Array([value]);
+ return new Scalar(TypeF16, arr[0], arr);
+}
+/** Create an f32 from a bit representation, a uint32 represented as a JS `number`. */
+export function f32Bits(bits) {
+ const arr = new Uint32Array([bits]);
+ return new Scalar(TypeF32, new Float32Array(arr.buffer)[0], arr);
+}
+/** Create an f16 from a bit representation, a uint16 represented as a JS `number`. */
+export function f16Bits(bits) {
+ const arr = new Uint16Array([bits]);
+ return new Scalar(TypeF16, new Float16Array(arr.buffer)[0], arr);
+}
+
+/** Create an i32 from a numeric value, a JS `number`. */
+export function i32(value) {
+ const arr = new Int32Array([value]);
+ return new Scalar(TypeI32, arr[0], arr);
+}
+/** Create an i16 from a numeric value, a JS `number`. */
+export function i16(value) {
+ const arr = new Int16Array([value]);
+ return new Scalar(TypeI16, arr[0], arr);
+}
+/** Create an i8 from a numeric value, a JS `number`. */
+export function i8(value) {
+ const arr = new Int8Array([value]);
+ return new Scalar(TypeI8, arr[0], arr);
+}
+
+/** Create an i32 from a bit representation, a uint32 represented as a JS `number`. */
+export function i32Bits(bits) {
+ const arr = new Uint32Array([bits]);
+ return new Scalar(TypeI32, new Int32Array(arr.buffer)[0], arr);
+}
+/** Create an i16 from a bit representation, a uint16 represented as a JS `number`. */
+export function i16Bits(bits) {
+ const arr = new Uint16Array([bits]);
+ return new Scalar(TypeI16, new Int16Array(arr.buffer)[0], arr);
+}
+/** Create an i8 from a bit representation, a uint8 represented as a JS `number`. */
+export function i8Bits(bits) {
+ const arr = new Uint8Array([bits]);
+ return new Scalar(TypeI8, new Int8Array(arr.buffer)[0], arr);
+}
+
+/** Create a u32 from a numeric value, a JS `number`. */
+export function u32(value) {
+ const arr = new Uint32Array([value]);
+ return new Scalar(TypeU32, arr[0], arr);
+}
+/** Create a u16 from a numeric value, a JS `number`. */
+export function u16(value) {
+ const arr = new Uint16Array([value]);
+ return new Scalar(TypeU16, arr[0], arr);
+}
+/** Create a u8 from a numeric value, a JS `number`. */
+export function u8(value) {
+ const arr = new Uint8Array([value]);
+ return new Scalar(TypeU8, arr[0], arr);
+}
+
+/** Create an u32 from a bit representation, a uint32 represented as a JS `number`. */
+export function u32Bits(bits) {
+ const arr = new Uint32Array([bits]);
+ return new Scalar(TypeU32, bits, arr);
+}
+/** Create an u16 from a bit representation, a uint16 represented as a JS `number`. */
+export function u16Bits(bits) {
+ const arr = new Uint16Array([bits]);
+ return new Scalar(TypeU16, bits, arr);
+}
+/** Create an u8 from a bit representation, a uint8 represented as a JS `number`. */
+export function u8Bits(bits) {
+ const arr = new Uint8Array([bits]);
+ return new Scalar(TypeU8, bits, arr);
+}
+
+/** Create a boolean value. */
+export function bool(value) {
+ // WGSL does not support using 'bool' types directly in storage / uniform
+ // buffers, so instead we pack booleans in a u32, where 'false' is zero and
+ // 'true' is any non-zero value.
+ const arr = new Uint32Array([value ? 1 : 0]);
+ return new Scalar(TypeBool, value, arr);
+}
+
+/** A 'true' literal value */
+export const True = bool(true);
+
+/** A 'false' literal value */
+export const False = bool(false);
+
+export function reinterpretF32AsU32(f32) {
+ const array = new Float32Array(1);
+ array[0] = f32;
+ return new Uint32Array(array.buffer)[0];
+}
+
+export function reinterpretU32AsF32(u32) {
+ const array = new Uint32Array(1);
+ array[0] = u32;
+ return new Float32Array(array.buffer)[0];
+}
+
+/**
+ * Class that encapsulates a vector value.
+ */
+export class Vector {
+ constructor(elements) {
+ if (elements.length < 2 || elements.length > 4) {
+ throw new Error(`vector element count must be between 2 and 4, got ${elements.length}`);
+ }
+ for (let i = 1; i < elements.length; i++) {
+ const a = elements[0].type;
+ const b = elements[i].type;
+ if (a !== b) {
+ throw new Error(
+ `cannot mix vector element types. Found elements with types '${a}' and '${b}'`
+ );
+ }
+ }
+ this.elements = elements;
+ this.type = TypeVec(elements.length, elements[0].type);
+ }
+
+ /**
+ * Copies the vector value to the Uint8Array buffer at the provided byte offset.
+ * @param buffer the destination buffer
+ * @param offset the byte offset within buffer
+ */
+ copyTo(buffer, offset) {
+ for (const element of this.elements) {
+ element.copyTo(buffer, offset);
+ offset += this.type.elementType.size;
+ }
+ }
+
+ /**
+ * @returns the WGSL representation of this vector value
+ */
+ wgsl() {
+ const els = this.elements.map(v => v.wgsl()).join(', ');
+ return `vec${this.type.width}(${els})`;
+ }
+
+ toString() {
+ return `${this.type}(${this.elements.map(e => e.toString()).join(', ')})`;
+ }
+
+ get x() {
+ assert(0 < this.elements.length);
+ return this.elements[0];
+ }
+
+ get y() {
+ assert(1 < this.elements.length);
+ return this.elements[1];
+ }
+
+ get z() {
+ assert(2 < this.elements.length);
+ return this.elements[2];
+ }
+
+ get w() {
+ assert(3 < this.elements.length);
+ return this.elements[3];
+ }
+}
+
+/** Helper for constructing a new two-element vector with the provided values */
+export function vec2(x, y) {
+ return new Vector([x, y]);
+}
+
+/** Helper for constructing a new three-element vector with the provided values */
+export function vec3(x, y, z) {
+ return new Vector([x, y, z]);
+}
+
+/** Helper for constructing a new four-element vector with the provided values */
+export function vec4(x, y, z, w) {
+ return new Vector([x, y, z, w]);
+}
+
+/**
+ * Helper for constructing Vectors from arrays of numbers
+ *
+ * @param v array of numbers to be converted, must contain 2, 3 or 4 elements
+ * @param op function to convert from number to Scalar, e.g. 'f32`
+ */
+export function toVector(v, op) {
+ switch (v.length) {
+ case 2:
+ return vec2(op(v[0]), op(v[1]));
+ case 3:
+ return vec3(op(v[0]), op(v[1]), op(v[2]));
+ case 4:
+ return vec4(op(v[0]), op(v[1]), op(v[2]), op(v[3]));
+ }
+
+ unreachable(`input to 'toVector' must contain 2, 3, or 4 elements`);
+}
+
+/** Value is a Scalar or Vector value. */
+
+export function serializeValue(v) {
+ const value = (kind, s) => {
+ switch (kind) {
+ case 'f32':
+ return new Uint32Array(s.bits.buffer)[0];
+ case 'f16':
+ return new Uint16Array(s.bits.buffer)[0];
+ default:
+ return s.value;
+ }
+ };
+ if (v instanceof Scalar) {
+ const kind = v.type.kind;
+ return {
+ kind: 'scalar',
+ type: kind,
+ value: value(kind, v),
+ };
+ }
+ if (v instanceof Vector) {
+ const kind = v.type.elementType.kind;
+ return {
+ kind: 'vector',
+ type: kind,
+ value: v.elements.map(e => value(kind, e)),
+ };
+ }
+ unreachable(`unhandled value type: ${v}`);
+}
+
+export function deserializeValue(data) {
+ const buildScalar = v => {
+ switch (data.type) {
+ case 'f64':
+ return f64(v);
+ case 'i32':
+ return i32(v);
+ case 'u32':
+ return u32(v);
+ case 'f32':
+ return f32Bits(v);
+ case 'i16':
+ return i16(v);
+ case 'u16':
+ return u16(v);
+ case 'f16':
+ return f16Bits(v);
+ case 'i8':
+ return i8(v);
+ case 'u8':
+ return u8(v);
+ case 'bool':
+ return bool(v);
+ default:
+ unreachable(`unhandled value type: ${data.type}`);
+ }
+ };
+ switch (data.kind) {
+ case 'scalar': {
+ return buildScalar(data.value);
+ }
+ case 'vector': {
+ return new Vector(data.value.map(v => buildScalar(v)));
+ }
+ }
+}
+
+/** @returns if the Value is a float scalar type */
+export function isFloatValue(v) {
+ if (v instanceof Scalar) {
+ const s = v;
+ return s.type.kind === 'f64' || s.type.kind === 'f32' || s.type.kind === 'f16';
+ }
+ return false;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/copy_to_texture.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/copy_to_texture.js
new file mode 100644
index 0000000000..dc04b1de84
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/copy_to_texture.js
@@ -0,0 +1,176 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, memcpy } from '../../common/util/util.js';
+import { GPUTest } from '../gpu_test.js';
+import { reifyExtent3D, reifyOrigin3D } from '../util/unions.js';
+
+import { makeInPlaceColorConversion } from './color_space_conversion.js';
+import { TexelView } from './texture/texel_view.js';
+import { textureContentIsOKByT2B } from './texture/texture_ok.js';
+
+/**
+ * Predefined copy sub rect meta infos.
+ */
+export const kCopySubrectInfo = [
+ {
+ srcOrigin: { x: 2, y: 2 },
+ dstOrigin: { x: 0, y: 0, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 4, height: 4 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+ {
+ srcOrigin: { x: 10, y: 2 },
+ dstOrigin: { x: 0, y: 0, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 4, height: 4 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+ {
+ srcOrigin: { x: 2, y: 10 },
+ dstOrigin: { x: 0, y: 0, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 4, height: 4 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+ {
+ srcOrigin: { x: 10, y: 10 },
+ dstOrigin: { x: 0, y: 0, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 4, height: 4 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+ {
+ srcOrigin: { x: 2, y: 2 },
+ dstOrigin: { x: 2, y: 2, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 16, height: 16 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+ {
+ srcOrigin: { x: 10, y: 2 },
+ dstOrigin: { x: 2, y: 2, z: 0 },
+ srcSize: { width: 16, height: 16 },
+ dstSize: { width: 16, height: 16 },
+ copyExtent: { width: 4, height: 4, depthOrArrayLayers: 1 },
+ },
+];
+
+export class CopyToTextureUtils extends GPUTest {
+ doFlipY(sourcePixels, width, height, bytesPerPixel) {
+ const dstPixels = new Uint8ClampedArray(width * height * bytesPerPixel);
+ for (let i = 0; i < height; ++i) {
+ for (let j = 0; j < width; ++j) {
+ const srcPixelPos = i * width + j;
+ // WebGL readPixel returns pixels from bottom-left origin. Using CopyExternalImageToTexture
+ // to copy from WebGL Canvas keeps top-left origin. So the expectation from webgl.readPixel should
+ // be flipped.
+ const dstPixelPos = (height - i - 1) * width + j;
+
+ memcpy(
+ { src: sourcePixels, start: srcPixelPos * bytesPerPixel, length: bytesPerPixel },
+ { dst: dstPixels, start: dstPixelPos * bytesPerPixel }
+ );
+ }
+ }
+
+ return dstPixels;
+ }
+
+ getExpectedDstPixelsFromSrcPixels({
+ srcPixels,
+ srcOrigin,
+ srcSize,
+ dstOrigin,
+ dstSize,
+ subRectSize,
+ format,
+ flipSrcBeforeCopy,
+ srcDoFlipYDuringCopy,
+ conversion,
+ }) {
+ const applyConversion = makeInPlaceColorConversion(conversion);
+
+ const reifySrcOrigin = reifyOrigin3D(srcOrigin);
+ const reifySrcSize = reifyExtent3D(srcSize);
+ const reifyDstOrigin = reifyOrigin3D(dstOrigin);
+ const reifyDstSize = reifyExtent3D(dstSize);
+ const reifySubRectSize = reifyExtent3D(subRectSize);
+
+ assert(
+ reifyDstOrigin.x + reifySubRectSize.width <= reifyDstSize.width &&
+ reifyDstOrigin.y + reifySubRectSize.height <= reifyDstSize.height,
+ 'subrect is out of bounds'
+ );
+
+ const divide = 255.0;
+ return TexelView.fromTexelsAsColors(
+ format,
+ coords => {
+ assert(
+ coords.x >= reifyDstOrigin.x &&
+ coords.y >= reifyDstOrigin.y &&
+ coords.x < reifyDstOrigin.x + reifySubRectSize.width &&
+ coords.y < reifyDstOrigin.y + reifySubRectSize.height &&
+ coords.z === 0,
+ 'out of bounds'
+ );
+
+ // Map dst coords to get candidate src pixel position in y.
+ let yInSubRect = coords.y - reifyDstOrigin.y;
+
+ // If srcDoFlipYDuringCopy is true, a flipY op has been applied to src during copy.
+ // WebGPU spec requires origin option relative to the top-left corner of the source image,
+ // increasing downward consistently.
+ // https://www.w3.org/TR/webgpu/#dom-gpuimagecopyexternalimage-flipy
+ // Flip only happens in copy rect contents and src origin always top-left.
+ // Get candidate src pixel position in y by mirroring in copy sub rect.
+ if (srcDoFlipYDuringCopy) yInSubRect = reifySubRectSize.height - 1 - yInSubRect;
+
+ let src_y = yInSubRect + reifySrcOrigin.y;
+
+ // Test might generate flipped source based on srcPixels, e.g. Create ImageBitmap based on srcPixels but set orientation to 'flipY'
+ // Get candidate src pixel position in y by mirroring in source.
+ if (flipSrcBeforeCopy) src_y = reifySrcSize.height - src_y - 1;
+
+ const pixelPos =
+ src_y * reifySrcSize.width + (coords.x - reifyDstOrigin.x) + reifySrcOrigin.x;
+
+ const rgba = {
+ R: srcPixels[pixelPos * 4] / divide,
+ G: srcPixels[pixelPos * 4 + 1] / divide,
+ B: srcPixels[pixelPos * 4 + 2] / divide,
+ A: srcPixels[pixelPos * 4 + 3] / divide,
+ };
+ applyConversion(rgba);
+ return rgba;
+ },
+ { clampToFormatRange: true }
+ );
+ }
+
+ doTestAndCheckResult(
+ imageCopyExternalImage,
+ dstTextureCopyView,
+ expTexelView,
+ copySize,
+ texelCompareOptions
+ ) {
+ this.device.queue.copyExternalImageToTexture(
+ imageCopyExternalImage,
+ dstTextureCopyView,
+ copySize
+ );
+
+ const resultPromise = textureContentIsOKByT2B(
+ this,
+ { texture: dstTextureCopyView.texture, origin: dstTextureCopyView.origin },
+ copySize,
+ { expTexelView },
+ texelCompareOptions
+ );
+
+ this.eventualExpectOK(resultPromise);
+ this.trackForCleanup(dstTextureCopyView.texture);
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/create_elements.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/create_elements.js
new file mode 100644
index 0000000000..da18d1fabf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/create_elements.js
@@ -0,0 +1,69 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { unreachable } from '../../common/util/util.js';
+// TESTING_TODO: This should expand to more canvas types (which will enhance a bunch of tests):
+// - canvas element not in dom
+// - canvas element in dom
+// - offscreen canvas from transferControlToOffscreen from canvas not in dom
+// - offscreen canvas from transferControlToOffscreen from canvas in dom
+// - offscreen canvas from new OffscreenCanvas
+export const kAllCanvasTypes = ['onscreen', 'offscreen'];
+
+/** Valid contextId for HTMLCanvasElement/OffscreenCanvas,
+ * spec: https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-getcontext
+ */
+export const kValidCanvasContextIds = ['2d', 'bitmaprenderer', 'webgl', 'webgl2', 'webgpu'];
+
+/** Helper(s) to determine if context is copyable. */
+export function canCopyFromCanvasContext(contextName) {
+ switch (contextName) {
+ case '2d':
+ case 'webgl':
+ case 'webgl2':
+ case 'webgpu':
+ return true;
+ default:
+ return false;
+ }
+}
+
+/** Create HTMLCanvas/OffscreenCanvas. */
+export function createCanvas(test, canvasType, width, height) {
+ if (canvasType === 'onscreen') {
+ if (typeof document !== 'undefined') {
+ return createOnscreenCanvas(test, width, height);
+ } else {
+ test.skip('Cannot create HTMLCanvasElement');
+ }
+ } else if (canvasType === 'offscreen') {
+ if (typeof OffscreenCanvas !== 'undefined') {
+ return createOffscreenCanvas(test, width, height);
+ } else {
+ test.skip('Cannot create an OffscreenCanvas');
+ }
+ } else {
+ unreachable();
+ }
+}
+
+/** Create HTMLCanvasElement. */
+export function createOnscreenCanvas(test, width, height) {
+ let canvas;
+ if (typeof document !== 'undefined') {
+ canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ } else {
+ test.skip('Cannot create HTMLCanvasElement');
+ }
+ return canvas;
+}
+
+/** Create OffscreenCanvas. */
+export function createOffscreenCanvas(test, width, height) {
+ if (typeof OffscreenCanvas === 'undefined') {
+ test.skip('OffscreenCanvas is not supported');
+ }
+
+ return new OffscreenCanvas(width, height);
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js
new file mode 100644
index 0000000000..021d02a625
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/device_pool.js
@@ -0,0 +1,361 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { SkipTestCase } from '../../common/framework/fixture.js';
+import { attemptGarbageCollection } from '../../common/util/collect_garbage.js';
+import { getGPU } from '../../common/util/navigator_gpu.js';
+import {
+ assert,
+ raceWithRejectOnTimeout,
+ assertReject,
+ unreachable,
+} from '../../common/util/util.js';
+import { kLimitInfo, kLimits } from '../capability_info.js';
+
+class TestFailedButDeviceReusable extends Error {}
+class FeaturesNotSupported extends Error {}
+export class TestOOMedShouldAttemptGC extends Error {}
+
+export class DevicePool {
+ holders = 'uninitialized';
+
+ /** Acquire a device from the pool and begin the error scopes. */
+ async acquire(descriptor) {
+ let errorMessage = '';
+ if (this.holders === 'uninitialized') {
+ this.holders = new DescriptorToHolderMap();
+ try {
+ await this.holders.getOrCreate(undefined);
+ } catch (ex) {
+ this.holders = 'failed';
+ if (ex instanceof Error) {
+ errorMessage = ` with ${ex.name} "${ex.message}"`;
+ }
+ }
+ }
+
+ assert(
+ this.holders !== 'failed',
+ `WebGPU device failed to initialize${errorMessage}; not retrying`
+ );
+
+ const holder = await this.holders.getOrCreate(descriptor);
+
+ assert(holder.state === 'free', 'Device was in use on DevicePool.acquire');
+ holder.state = 'acquired';
+ holder.beginTestScope();
+ return holder;
+ }
+
+ /**
+ * End the error scopes and check for errors.
+ * Then, if the device seems reusable, release it back into the pool. Otherwise, drop it.
+ */
+ async release(holder) {
+ assert(this.holders instanceof DescriptorToHolderMap, 'DevicePool got into a bad state');
+ assert(holder instanceof DeviceHolder, 'DeviceProvider should always be a DeviceHolder');
+
+ assert(holder.state === 'acquired', 'trying to release a device while already released');
+ try {
+ await holder.endTestScope();
+
+ // (Hopefully if the device was lost, it has been reported by the time endErrorScopes()
+ // has finished (or timed out). If not, it could cause a finite number of extra test
+ // failures following this one (but should recover eventually).)
+ assert(
+ holder.lostInfo === undefined,
+ `Device was unexpectedly lost. Reason: ${holder.lostInfo?.reason}, Message: ${holder.lostInfo?.message}`
+ );
+ } catch (ex) {
+ // Any error that isn't explicitly TestFailedButDeviceReusable forces a new device to be
+ // created for the next test.
+ if (!(ex instanceof TestFailedButDeviceReusable)) {
+ this.holders.delete(holder);
+ if ('destroy' in holder.device) {
+ holder.device.destroy();
+ }
+
+ // Release the (hopefully only) ref to the GPUDevice.
+ holder.releaseGPUDevice();
+
+ // Try to clean up, in case there are stray GPU resources in need of collection.
+ if (ex instanceof TestOOMedShouldAttemptGC) {
+ await attemptGarbageCollection();
+ }
+ }
+ // In the try block, we may throw an error if the device is lost in order to force device
+ // reinitialization, however, if the device lost was expected we want to suppress the error
+ // The device lost is expected when `holder.expectedLostReason` is equal to
+ // `holder.lostInfo.reason`.
+ const expectedDeviceLost =
+ holder.expectedLostReason !== undefined &&
+ holder.lostInfo !== undefined &&
+ holder.expectedLostReason === holder.lostInfo.reason;
+ if (!expectedDeviceLost) {
+ throw ex;
+ }
+ } finally {
+ // Mark the holder as free so the device can be reused (if it's still in this.devices).
+ holder.state = 'free';
+ }
+ }
+}
+
+/**
+ * Map from GPUDeviceDescriptor to DeviceHolder.
+ */
+class DescriptorToHolderMap {
+ /** Map keys that are known to be unsupported and can be rejected quickly. */
+ unsupported = new Set();
+ holders = new Map();
+
+ /** Deletes an item from the map by DeviceHolder value. */
+ delete(holder) {
+ for (const [k, v] of this.holders) {
+ if (v === holder) {
+ this.holders.delete(k);
+ return;
+ }
+ }
+ unreachable("internal error: couldn't find DeviceHolder to delete");
+ }
+
+ /**
+ * Gets a DeviceHolder from the map if it exists; otherwise, calls create() to create one,
+ * inserts it, and returns it.
+ *
+ * If an `uncanonicalizedDescriptor` is provided, it is canonicalized and used as the map key.
+ * If one is not provided, the map key is `""` (empty string).
+ *
+ * Throws SkipTestCase if devices with this descriptor are unsupported.
+ */
+ async getOrCreate(uncanonicalizedDescriptor) {
+ const [descriptor, key] = canonicalizeDescriptor(uncanonicalizedDescriptor);
+ // Quick-reject descriptors that are known to be unsupported already.
+ if (this.unsupported.has(key)) {
+ throw new SkipTestCase(
+ `GPUDeviceDescriptor previously failed: ${JSON.stringify(descriptor)}`
+ );
+ }
+
+ // Search for an existing device with the same descriptor.
+ {
+ const value = this.holders.get(key);
+ if (value) {
+ // Move it to the end of the Map (most-recently-used).
+ this.holders.delete(key);
+ this.holders.set(key, value);
+ return value;
+ }
+ }
+
+ // No existing item was found; add a new one.
+ let value;
+ try {
+ value = await DeviceHolder.create(descriptor);
+ } catch (ex) {
+ if (ex instanceof FeaturesNotSupported) {
+ this.unsupported.add(key);
+ throw new SkipTestCase(
+ `GPUDeviceDescriptor not supported: ${JSON.stringify(descriptor)}\n${ex?.message ?? ''}`
+ );
+ }
+
+ throw ex;
+ }
+ this.insertAndCleanUp(key, value);
+ return value;
+ }
+
+ /** Insert an entry, then remove the least-recently-used items if there are too many. */
+ insertAndCleanUp(key, value) {
+ this.holders.set(key, value);
+
+ const kMaxEntries = 5;
+ if (this.holders.size > kMaxEntries) {
+ // Delete the first (least recently used) item in the set.
+ for (const [key] of this.holders) {
+ this.holders.delete(key);
+ return;
+ }
+ }
+ }
+}
+
+/**
+ * Make a stringified map-key from a GPUDeviceDescriptor.
+ * Tries to make sure all defaults are resolved, first - but it's okay if some are missed
+ * (it just means some GPUDevice objects won't get deduplicated).
+ *
+ * This does **not** canonicalize `undefined` (the "default" descriptor) into a fully-qualified
+ * GPUDeviceDescriptor. This is just because `undefined` is a common case and we want to use it
+ * as a sanity check that WebGPU is working.
+ */
+function canonicalizeDescriptor(desc) {
+ if (desc === undefined) {
+ return [undefined, ''];
+ }
+
+ const featuresCanonicalized = desc.requiredFeatures
+ ? Array.from(new Set(desc.requiredFeatures)).sort()
+ : [];
+
+ /** Canonicalized version of the requested limits: in canonical order, with only values which are
+ * specified _and_ non-default. */
+ const limitsCanonicalized = {};
+ if (desc.requiredLimits) {
+ for (const limit of kLimits) {
+ const requestedValue = desc.requiredLimits[limit];
+ const defaultValue = kLimitInfo[limit].default;
+ // Skip adding a limit to limitsCanonicalized if it is the same as the default.
+ if (requestedValue !== undefined && requestedValue !== defaultValue) {
+ limitsCanonicalized[limit] = requestedValue;
+ }
+ }
+ }
+
+ // Type ensures every field is carried through.
+ const descriptorCanonicalized = {
+ requiredFeatures: featuresCanonicalized,
+ requiredLimits: limitsCanonicalized,
+ defaultQueue: {},
+ };
+ return [descriptorCanonicalized, JSON.stringify(descriptorCanonicalized)];
+}
+
+function supportsFeature(adapter, descriptor) {
+ if (descriptor === undefined) {
+ return true;
+ }
+
+ for (const feature of descriptor.requiredFeatures) {
+ if (!adapter.features.has(feature)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * DeviceHolder has three states:
+ * - 'free': Free to be used for a new test.
+ * - 'acquired': In use by a running test.
+ */
+
+/**
+ * Holds a GPUDevice and tracks its state (free/acquired) and handles device loss.
+ */
+class DeviceHolder {
+ /** The device. Will be cleared during cleanup if there were unexpected errors. */
+
+ /** Whether the device is in use by a test or not. */
+ state = 'free';
+ /** initially undefined; becomes set when the device is lost */
+
+ // Gets a device and creates a DeviceHolder.
+ // If the device is lost, DeviceHolder.lost gets set.
+ static async create(descriptor) {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+ assert(adapter !== null, 'requestAdapter returned null');
+ if (!supportsFeature(adapter, descriptor)) {
+ throw new FeaturesNotSupported('One or more features are not supported');
+ }
+ const device = await adapter.requestDevice(descriptor);
+ assert(device !== null, 'requestDevice returned null');
+
+ return new DeviceHolder(device);
+ }
+
+ constructor(device) {
+ this._device = device;
+ void this._device.lost.then(ev => {
+ this.lostInfo = ev;
+ });
+ }
+
+ get device() {
+ assert(this._device !== undefined);
+ return this._device;
+ }
+
+ /** Push error scopes that surround test execution. */
+ beginTestScope() {
+ assert(this.state === 'acquired');
+ this.device.pushErrorScope('out-of-memory');
+ this.device.pushErrorScope('validation');
+ }
+
+ /** Mark the DeviceHolder as expecting a device loss when the test scope ends. */
+ expectDeviceLost(reason) {
+ assert(this.state === 'acquired');
+ this.expectedLostReason = reason;
+ }
+
+ /**
+ * Attempt to end test scopes: Check that there are no extra error scopes, and that no
+ * otherwise-uncaptured errors occurred during the test. Time out if it takes too long.
+ */
+ endTestScope() {
+ assert(this.state === 'acquired');
+ const kTimeout = 5000;
+
+ // Time out if attemptEndTestScope (popErrorScope or onSubmittedWorkDone) never completes. If
+ // this rejects, the device won't be reused, so it's OK that popErrorScope calls may not have
+ // finished.
+ //
+ // This could happen due to a browser bug - e.g.,
+ // as of this writing, on Chrome GPU process crash, popErrorScope just hangs.
+ return raceWithRejectOnTimeout(this.attemptEndTestScope(), kTimeout, 'endTestScope timed out');
+ }
+
+ async attemptEndTestScope() {
+ let gpuValidationError;
+ let gpuOutOfMemoryError;
+
+ // Submit to the queue to attempt to force a GPU flush.
+ this.device.queue.submit([]);
+
+ try {
+ // May reject if the device was lost.
+ [gpuValidationError, gpuOutOfMemoryError] = await Promise.all([
+ this.device.popErrorScope(),
+ this.device.popErrorScope(),
+ ]);
+ } catch (ex) {
+ assert(this.lostInfo !== undefined, 'popErrorScope failed; did beginTestScope get missed?');
+ throw ex;
+ }
+
+ // Attempt to wait for the queue to be idle.
+ if (this.device.queue.onSubmittedWorkDone) {
+ await this.device.queue.onSubmittedWorkDone();
+ }
+
+ await assertReject(
+ this.device.popErrorScope(),
+ 'There was an extra error scope on the stack after a test'
+ );
+
+ if (gpuValidationError !== null) {
+ assert(gpuValidationError instanceof GPUValidationError);
+ // Allow the device to be reused.
+ throw new TestFailedButDeviceReusable(
+ `Unexpected validation error occurred: ${gpuValidationError.message}`
+ );
+ }
+ if (gpuOutOfMemoryError !== null) {
+ assert(gpuOutOfMemoryError instanceof GPUOutOfMemoryError);
+ // Don't allow the device to be reused; unexpected OOM could break the device.
+ throw new TestOOMedShouldAttemptGC('Unexpected out-of-memory error occurred');
+ }
+ }
+
+ /**
+ * Release the ref to the GPUDevice. This should be the only ref held by the DevicePool or
+ * GPUTest, so in theory it can get garbage collected.
+ */
+ releaseGPUDevice() {
+ this._device = undefined;
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/f32_interval.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/f32_interval.js
new file mode 100644
index 0000000000..68a610b7b9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/f32_interval.js
@@ -0,0 +1,1931 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../common/util/util.js';
+import { Float16Array } from '../../external/petamoriken/float16/float16.js';
+import { kValue } from './constants.js';
+import { reinterpretF32AsU32, reinterpretU32AsF32 } from './conversion.js';
+import {
+ calculatePermutations,
+ cartesianProduct,
+ correctlyRoundedF16,
+ correctlyRoundedF32,
+ flushSubnormalNumberF32,
+ isFiniteF16,
+ isFiniteF32,
+ isSubnormalNumberF16,
+ isSubnormalNumberF32,
+ oneULP,
+} from './math.js';
+
+/**
+ * Representation of bounds for an interval as an array with either one or two
+ * elements. Single element indicates that the interval is a single point. For
+ * two elements, the first is the lower bound of the interval and the second is
+ * the upper bound.
+ */
+
+/** Represents a closed interval in the f32 range */
+export class F32Interval {
+ /** Constructor
+ *
+ * `toF32Interval` is the preferred way to create F32Intervals
+ *
+ * @param bounds either a pair of numbers indicating the beginning then the
+ * end of the interval, or a single element array indicating the
+ * interval is a point
+ */
+ constructor(...bounds) {
+ const [begin, end] = bounds.length === 2 ? bounds : [bounds[0], bounds[0]];
+ assert(!Number.isNaN(begin) && !Number.isNaN(end), `bounds need to be non-NaN`);
+ assert(begin <= end, `bounds[0] (${begin}) must be less than or equal to bounds[1] (${end})`);
+
+ this.begin = begin;
+ this.end = end;
+ }
+
+ /** @returns begin and end if non-point interval, otherwise just begin */
+ bounds() {
+ return this.isPoint() ? [this.begin] : [this.begin, this.end];
+ }
+
+ /** @returns if a point or interval is completely contained by this interval */
+ contains(n) {
+ if (Number.isNaN(n)) {
+ // Being the any interval indicates that accuracy is not defined for this
+ // test, so the test is just checking that this input doesn't cause the
+ // implementation to misbehave, so NaN is accepted.
+ return this.begin === Number.NEGATIVE_INFINITY && this.end === Number.POSITIVE_INFINITY;
+ }
+ const i = toF32Interval(n);
+ return this.begin <= i.begin && this.end >= i.end;
+ }
+
+ /** @returns if any values in the interval may be flushed to zero, this
+ * includes any subnormals and zero itself.
+ */
+ containsZeroOrSubnormals() {
+ return !(
+ this.end < kValue.f32.subnormal.negative.min || this.begin > kValue.f32.subnormal.positive.max
+ );
+ }
+
+ /** @returns if this interval contains a single point */
+ isPoint() {
+ return this.begin === this.end;
+ }
+
+ /** @returns if this interval only contains f32 finite values */
+ isFinite() {
+ return isFiniteF32(this.begin) && isFiniteF32(this.end);
+ }
+
+ /** @returns an interval with the tightest bounds that includes all provided intervals */
+ static span(...intervals) {
+ assert(intervals.length > 0, `span of an empty list of F32Intervals is not allowed`);
+ let begin = Number.POSITIVE_INFINITY;
+ let end = Number.NEGATIVE_INFINITY;
+ intervals.forEach(i => {
+ begin = Math.min(i.begin, begin);
+ end = Math.max(i.end, end);
+ });
+ return new F32Interval(begin, end);
+ }
+
+ /** @returns a string representation for logging purposes */
+ toString() {
+ return `[${this.bounds()}]`;
+ }
+
+ /** @returns a singleton for interval of all possible values
+ * This interval is used in situations where accuracy is not defined, so any
+ * result is valid.
+ */
+ static any() {
+ if (this._any === undefined) {
+ this._any = new F32Interval(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
+ }
+ return this._any;
+ }
+}
+
+/**
+ * SerializedF32Interval holds the serialized form of a F32Interval.
+ * This form can be safely encoded to JSON.
+ */
+
+/** serializeF32Interval() converts a F32Interval to a SerializedF32Interval */
+export function serializeF32Interval(i) {
+ return i === F32Interval.any()
+ ? 'any'
+ : { begin: reinterpretF32AsU32(i.begin), end: reinterpretF32AsU32(i.end) };
+}
+
+/** serializeF32Interval() converts a SerializedF32Interval to a F32Interval */
+export function deserializeF32Interval(data) {
+ return data === 'any'
+ ? F32Interval.any()
+ : toF32Interval([reinterpretU32AsF32(data.begin), reinterpretU32AsF32(data.end)]);
+}
+
+/** @returns an interval containing the point or the original interval */
+export function toF32Interval(n) {
+ if (n instanceof F32Interval) {
+ return n;
+ }
+
+ if (n instanceof Array) {
+ return new F32Interval(...n);
+ }
+
+ return new F32Interval(n, n);
+}
+
+/** F32Interval of [-π, π] */
+const kNegPiToPiInterval = toF32Interval([
+ kValue.f32.negative.pi.whole,
+ kValue.f32.positive.pi.whole,
+]);
+
+/** F32Interval of values greater than 0 and less than or equal to f32 max */
+const kGreaterThanZeroInterval = toF32Interval([
+ kValue.f32.subnormal.positive.min,
+ kValue.f32.positive.max,
+]);
+
+/** Representation of a vec2/3/4 of floating point intervals as an array of F32Intervals */
+
+/** Coerce F32Interval[] to F32Vector if possible */
+function isF32Vector(v) {
+ if (v[0] instanceof F32Interval) {
+ return v.length === 2 || v.length === 3 || v.length === 4;
+ }
+ return false;
+}
+
+/** @returns an F32Vector representation of an array fo F32Intervals if possible */
+export function toF32Vector(v) {
+ if (isF32Vector(v)) {
+ return v;
+ }
+
+ const f = v.map(toF32Interval);
+ if (isF32Vector(f)) {
+ return f;
+ }
+ unreachable(`Cannot convert [${v}] to F32Vector`);
+}
+
+/** F32Vector with all zero elements */
+const kZeroVector = {
+ 2: toF32Vector([0, 0]),
+ 3: toF32Vector([0, 0, 0]),
+ 4: toF32Vector([0, 0, 0, 0]),
+};
+
+/** F32Vector with all F32Interval.any() elements */
+const kAnyVector = {
+ 2: toF32Vector([F32Interval.any(), F32Interval.any()]),
+ 3: toF32Vector([F32Interval.any(), F32Interval.any(), F32Interval.any()]),
+ 4: toF32Vector([F32Interval.any(), F32Interval.any(), F32Interval.any(), F32Interval.any()]),
+};
+
+/**
+ * @returns a F32Vector where each element is the span for corresponding
+ * elements at the same index in the input vectors
+ */
+function spanF32Vector(...vectors) {
+ const vector_length = vectors[0].length;
+ assert(
+ vectors.every(e => e.length === vector_length),
+ `Vector span is not defined for vectors of differing lengths`
+ );
+
+ // The outer map is doing the walk across a single F32Vector to get the indices to use.
+ // The inner map is doing the walk across the of the vector array, collecting the value of each vector at the
+ // index, then spanning them down to a single F32Interval.
+ // The toF32Vector coerces things at the end to be a F32Vector, because the outer .map() will actually return a
+ // F32Interval[]
+ return toF32Vector(
+ vectors[0].map((_, idx) => {
+ return F32Interval.span(...vectors.map(v => v[idx]));
+ })
+ );
+}
+
+/**
+ * @retuns the vector result of multiplying the given vector by the given scalar
+ */
+function multiplyVectorByScalar(v, c) {
+ return toF32Vector(v.map(x => multiplicationInterval(x, c)));
+}
+
+/**
+ * @returns the input plus zero if any of the entries are f32 subnormal,
+ * otherwise returns the input.
+ */
+function addFlushedIfNeededF32(values) {
+ return values.some(v => v !== 0 && isSubnormalNumberF32(v)) ? values.concat(0) : values;
+}
+
+/**
+ * @returns the input plus zero if any of the entries are f16 subnormal,
+ * otherwise returns the input
+ */
+function addFlushedIfNeededF16(values) {
+ return values.some(v => v !== 0 && isSubnormalNumberF16(v)) ? values.concat(0) : values;
+}
+
+/**
+ * A function that converts a point to an acceptance interval.
+ * This is the public facing API for builtin implementations that is called
+ * from tests.
+ */
+
+/**
+ * Restrict the inputs to an PointToInterval operation
+ *
+ * Only used for operations that have tighter domain requirements than 'must be
+ * f32 finite'.
+ *
+ * @param domain interval to restrict inputs to
+ * @param impl operation implementation to run if input is within the required domain
+ * @returns a PointToInterval that calls impl if domain contains the input,
+ * otherwise it returns the any() interval */
+function limitPointToIntervalDomain(domain, impl) {
+ return n => {
+ return domain.contains(n) ? impl(n) : F32Interval.any();
+ };
+}
+
+/**
+ * A function that converts a pair of points to an acceptance interval.
+ * This is the public facing API for builtin implementations that is called
+ * from tests.
+ */
+
+/**
+ * Restrict the inputs to a BinaryToInterval
+ *
+ * Only used for operations that have tighter domain requirements than 'must be
+ * f32 finite'.
+ *
+ * @param domain set of intervals to restrict inputs to
+ * @param impl operation implementation to run if input is within the required domain
+ * @returns a BinaryToInterval that calls impl if domain contains the input,
+ * otherwise it returns the any() interval */
+function limitBinaryToIntervalDomain(domain, impl) {
+ return (x, y) => {
+ if (!domain.x.some(d => d.contains(x)) || !domain.y.some(d => d.contains(y))) {
+ return F32Interval.any();
+ }
+
+ return impl(x, y);
+ };
+}
+
+/**
+ * A function that converts a triplet of points to an acceptance interval.
+ * This is the public facing API for builtin implementations that is called
+ * from tests.
+ */
+
+/** Converts a point to an acceptance interval, using a specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ * op.extrema is invoked before this point in the call stack.
+ * op.domain is tested before this point in the call stack.
+ *
+ * @param n value to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function roundAndFlushPointToInterval(n, op) {
+ assert(!Number.isNaN(n), `flush not defined for NaN`);
+ const values = correctlyRoundedF32(n);
+ const inputs = addFlushedIfNeededF32(values);
+ const results = new Set(inputs.map(op.impl));
+ return F32Interval.span(...results);
+}
+
+/** Converts a pair to an acceptance interval, using a specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ * All unique combinations of x & y are run.
+ * op.extrema is invoked before this point in the call stack.
+ * op.domain is tested before this point in the call stack.
+ *
+ * @param x first param to flush & round then invoke op.impl on
+ * @param y second param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function roundAndFlushBinaryToInterval(x, y, op) {
+ assert(!Number.isNaN(x), `flush not defined for NaN`);
+ assert(!Number.isNaN(y), `flush not defined for NaN`);
+ const x_values = correctlyRoundedF32(x);
+ const y_values = correctlyRoundedF32(y);
+ const x_inputs = addFlushedIfNeededF32(x_values);
+ const y_inputs = addFlushedIfNeededF32(y_values);
+ const intervals = new Set();
+ x_inputs.forEach(inner_x => {
+ y_inputs.forEach(inner_y => {
+ intervals.add(op.impl(inner_x, inner_y));
+ });
+ });
+ return F32Interval.span(...intervals);
+}
+
+/** Converts a triplet to an acceptance interval, using a specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ * All unique combinations of x, y & z are run.
+ *
+ * @param x first param to flush & round then invoke op.impl on
+ * @param y second param to flush & round then invoke op.impl on
+ * @param z third param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function roundAndFlushTernaryToInterval(x, y, z, op) {
+ assert(!Number.isNaN(x), `flush not defined for NaN`);
+ assert(!Number.isNaN(y), `flush not defined for NaN`);
+ assert(!Number.isNaN(z), `flush not defined for NaN`);
+ const x_values = correctlyRoundedF32(x);
+ const y_values = correctlyRoundedF32(y);
+ const z_values = correctlyRoundedF32(z);
+ const x_inputs = addFlushedIfNeededF32(x_values);
+ const y_inputs = addFlushedIfNeededF32(y_values);
+ const z_inputs = addFlushedIfNeededF32(z_values);
+ const intervals = new Set();
+
+ x_inputs.forEach(inner_x => {
+ y_inputs.forEach(inner_y => {
+ z_inputs.forEach(inner_z => {
+ intervals.add(op.impl(inner_x, inner_y, inner_z));
+ });
+ });
+ });
+
+ return F32Interval.span(...intervals);
+}
+
+/** Converts a vector to an acceptance interval using a specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ *
+ * @param x param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function roundAndFlushVectorToInterval(x, op) {
+ assert(
+ x.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ const x_rounded = x.map(correctlyRoundedF32);
+ const x_flushed = x_rounded.map(addFlushedIfNeededF32);
+ const x_inputs = cartesianProduct(...x_flushed);
+
+ const intervals = new Set();
+ x_inputs.forEach(inner_x => {
+ intervals.add(op.impl(inner_x));
+ });
+ return F32Interval.span(...intervals);
+}
+
+/** Converts a pair of vectors to an acceptance interval using a specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ * All unique combinations of x & y are run.
+ *
+ * @param x first param to flush & round then invoke op.impl on
+ * @param y second param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function roundAndFlushVectorPairToInterval(x, y, op) {
+ assert(
+ x.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ assert(
+ y.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ const x_rounded = x.map(correctlyRoundedF32);
+ const y_rounded = y.map(correctlyRoundedF32);
+ const x_flushed = x_rounded.map(addFlushedIfNeededF32);
+ const y_flushed = y_rounded.map(addFlushedIfNeededF32);
+ const x_inputs = cartesianProduct(...x_flushed);
+ const y_inputs = cartesianProduct(...y_flushed);
+
+ const intervals = new Set();
+ x_inputs.forEach(inner_x => {
+ y_inputs.forEach(inner_y => {
+ intervals.add(op.impl(inner_x, inner_y));
+ });
+ });
+ return F32Interval.span(...intervals);
+}
+
+/** Converts a vector to a vector of acceptance intervals using a specific
+ * function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ *
+ * @param x param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a vector of spans for each outputs of op.impl
+ */
+function roundAndFlushVectorToVector(x, op) {
+ assert(
+ x.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ const x_rounded = x.map(correctlyRoundedF32);
+ const x_flushed = x_rounded.map(addFlushedIfNeededF32);
+ const x_inputs = cartesianProduct(...x_flushed);
+
+ const interval_vectors = new Set();
+ x_inputs.forEach(inner_x => {
+ interval_vectors.add(op.impl(inner_x));
+ });
+
+ return spanF32Vector(...interval_vectors);
+}
+
+/**
+ * Converts a pair of vectors to a vector of acceptance intervals using a
+ * specific function
+ *
+ * This handles correctly rounding and flushing inputs as needed.
+ * Duplicate inputs are pruned before invoking op.impl.
+ *
+ * @param x first param to flush & round then invoke op.impl on
+ * @param x second param to flush & round then invoke op.impl on
+ * @param op operation defining the function being run
+ * @returns a vector of spans for each output of op.impl
+ */
+function roundAndFlushVectorPairToVector(x, y, op) {
+ assert(
+ x.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ assert(
+ y.every(e => !Number.isNaN(e)),
+ `flush not defined for NaN`
+ );
+
+ const x_rounded = x.map(correctlyRoundedF32);
+ const y_rounded = y.map(correctlyRoundedF32);
+ const x_flushed = x_rounded.map(addFlushedIfNeededF32);
+ const y_flushed = y_rounded.map(addFlushedIfNeededF32);
+ const x_inputs = cartesianProduct(...x_flushed);
+ const y_inputs = cartesianProduct(...y_flushed);
+
+ const interval_vectors = new Set();
+ x_inputs.forEach(inner_x => {
+ y_inputs.forEach(inner_y => {
+ interval_vectors.add(op.impl(inner_x, inner_y));
+ });
+ });
+
+ return spanF32Vector(...interval_vectors);
+}
+
+/** Calculate the acceptance interval for a unary function over an interval
+ *
+ * If the interval is actually a point, this just decays to
+ * roundAndFlushPointToInterval.
+ *
+ * The provided domain interval may be adjusted if the operation defines an
+ * extrema function.
+ *
+ * @param x input domain interval
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function runPointToIntervalOp(x, op) {
+ if (!x.isFinite()) {
+ return F32Interval.any();
+ }
+
+ if (op.extrema !== undefined) {
+ x = op.extrema(x);
+ }
+
+ const result = F32Interval.span(...x.bounds().map(b => roundAndFlushPointToInterval(b, op)));
+ return result.isFinite() ? result : F32Interval.any();
+}
+
+/** Calculate the acceptance interval for a binary function over an interval
+ *
+ * The provided domain intervals may be adjusted if the operation defines an
+ * extrema function.
+ *
+ * @param x first input domain interval
+ * @param y second input domain interval
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function runBinaryToIntervalOp(x, y, op) {
+ if (!x.isFinite() || !y.isFinite()) {
+ return F32Interval.any();
+ }
+
+ if (op.extrema !== undefined) {
+ [x, y] = op.extrema(x, y);
+ }
+
+ const outputs = new Set();
+ x.bounds().forEach(inner_x => {
+ y.bounds().forEach(inner_y => {
+ outputs.add(roundAndFlushBinaryToInterval(inner_x, inner_y, op));
+ });
+ });
+
+ const result = F32Interval.span(...outputs);
+ return result.isFinite() ? result : F32Interval.any();
+}
+
+/** Calculate the acceptance interval for a ternary function over an interval
+ *
+ * @param x first input domain interval
+ * @param y second input domain interval
+ * @param z third input domain interval
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function runTernaryToIntervalOp(x, y, z, op) {
+ if (!x.isFinite() || !y.isFinite() || !z.isFinite()) {
+ return F32Interval.any();
+ }
+
+ const outputs = new Set();
+ x.bounds().forEach(inner_x => {
+ y.bounds().forEach(inner_y => {
+ z.bounds().forEach(inner_z => {
+ outputs.add(roundAndFlushTernaryToInterval(inner_x, inner_y, inner_z, op));
+ });
+ });
+ });
+
+ const result = F32Interval.span(...outputs);
+ return result.isFinite() ? result : F32Interval.any();
+}
+
+/** Calculate the acceptance interval for a vector function over given intervals
+ *
+ * @param x input domain intervals vector
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function runVectorToIntervalOp(x, op) {
+ if (x.some(e => !e.isFinite())) {
+ return F32Interval.any();
+ }
+
+ const x_values = cartesianProduct(...x.map(e => e.bounds()));
+
+ const outputs = new Set();
+ x_values.forEach(inner_x => {
+ outputs.add(roundAndFlushVectorToInterval(inner_x, op));
+ });
+
+ const result = F32Interval.span(...outputs);
+ return result.isFinite() ? result : F32Interval.any();
+}
+
+/** Calculate the acceptance interval for a vector pair function over given intervals
+ *
+ * @param x first input domain intervals vector
+ * @param y second input domain intervals vector
+ * @param op operation defining the function being run
+ * @returns a span over all of the outputs of op.impl
+ */
+function runVectorPairToIntervalOp(x, y, op) {
+ if (x.some(e => !e.isFinite()) || y.some(e => !e.isFinite())) {
+ return F32Interval.any();
+ }
+
+ const x_values = cartesianProduct(...x.map(e => e.bounds()));
+ const y_values = cartesianProduct(...y.map(e => e.bounds()));
+
+ const outputs = new Set();
+ x_values.forEach(inner_x => {
+ y_values.forEach(inner_y => {
+ outputs.add(roundAndFlushVectorPairToInterval(inner_x, inner_y, op));
+ });
+ });
+
+ const result = F32Interval.span(...outputs);
+ return result.isFinite() ? result : F32Interval.any();
+}
+
+/** Calculate the vector of acceptance intervals for a pair of vector function over
+ * given intervals
+ *
+ * @param x input domain intervals vector
+ * @param x input domain intervals vector
+ * @param op operation defining the function being run
+ * @returns a vector of spans over all of the outputs of op.impl
+ */
+function runVectorToVectorOp(x, op) {
+ if (x.some(e => !e.isFinite())) {
+ return kAnyVector[x.length];
+ }
+
+ const x_values = cartesianProduct(...x.map(e => e.bounds()));
+
+ const outputs = new Set();
+ x_values.forEach(inner_x => {
+ outputs.add(roundAndFlushVectorToVector(inner_x, op));
+ });
+
+ const result = spanF32Vector(...outputs);
+ return result.every(e => e.isFinite()) ? result : toF32Vector(x.map(_ => F32Interval.any()));
+}
+
+/**
+ * Calculate the vector of acceptance intervals by running a scalar operation
+ * component-wise over a vector.
+ *
+ * This is used for situations where a component-wise operation, like vector
+ * negation, is needed as part of a inherited accuracy, but the top-level
+ * operation test don't require an explicit vector definition of the function,
+ * due to the generated vectorize tests being sufficient.
+ *
+ * @param x input domain intervals vector
+ * @param op scalar operation to be run component-wise
+ * @returns a vector of intervals with the outputs of op.impl
+ */
+function runPointToIntervalOpComponentWise(x, op) {
+ return toF32Vector(
+ x.map(i => {
+ return runPointToIntervalOp(i, op);
+ })
+ );
+}
+
+/** Calculate the vector of acceptance intervals for a vector function over
+ * given intervals
+ *
+ * @param x first input domain intervals vector
+ * @param y second input domain intervals vector
+ * @param op operation defining the function being run
+ * @returns a vector of spans over all of the outputs of op.impl
+ */
+function runVectorPairToVectorOp(x, y, op) {
+ if (x.some(e => !e.isFinite()) || y.some(e => !e.isFinite())) {
+ return kAnyVector[x.length];
+ }
+
+ const x_values = cartesianProduct(...x.map(e => e.bounds()));
+ const y_values = cartesianProduct(...y.map(e => e.bounds()));
+
+ const outputs = new Set();
+ x_values.forEach(inner_x => {
+ y_values.forEach(inner_y => {
+ outputs.add(roundAndFlushVectorPairToVector(inner_x, inner_y, op));
+ });
+ });
+
+ const result = spanF32Vector(...outputs);
+ return result.every(e => e.isFinite()) ? result : toF32Vector(x.map(_ => F32Interval.any()));
+}
+
+/**
+ * Calculate the vector of acceptance intervals by running a scalar operation
+ * component-wise over a pair vectors.
+ *
+ * This is used for situations where a component-wise operation, like vector
+ * subtraction, is needed as part of a inherited accuracy, but the top-level
+ * operation test don't require an explicit vector definition of the function,
+ * due to the generated vectorize tests being sufficient.
+ *
+ * @param x first input domain intervals vector
+ * @param y second input domain intervals vector
+ * @param op scalar operation to be run component-wise
+ * @returns a vector of intervals with the outputs of op.impl
+ */
+function runBinaryToIntervalOpComponentWise(x, y, op) {
+ assert(
+ x.length === y.length,
+ `runBinaryToIntervalOpComponentWise requires vectors of the same length`
+ );
+
+ return toF32Vector(
+ x.map((i, idx) => {
+ return runBinaryToIntervalOp(i, y[idx], op);
+ })
+ );
+}
+
+/** Defines a PointToIntervalOp for an interval of the correctly rounded values around the point */
+const CorrectlyRoundedIntervalOp = {
+ impl: n => {
+ assert(!Number.isNaN(n), `absolute not defined for NaN`);
+ return toF32Interval(n);
+ },
+};
+
+/** @returns an interval of the correctly rounded values around the point */
+export function correctlyRoundedInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), CorrectlyRoundedIntervalOp);
+}
+
+/** @returns a PointToIntervalOp for [n - error_range, n + error_range] */
+function AbsoluteErrorIntervalOp(error_range) {
+ const op = {
+ impl: _ => {
+ return F32Interval.any();
+ },
+ };
+
+ if (isFiniteF32(error_range)) {
+ op.impl = n => {
+ assert(!Number.isNaN(n), `absolute error not defined for NaN`);
+ return toF32Interval([n - error_range, n + error_range]);
+ };
+ }
+
+ return op;
+}
+
+/** @returns an interval of the absolute error around the point */
+export function absoluteErrorInterval(n, error_range) {
+ error_range = Math.abs(error_range);
+ return runPointToIntervalOp(toF32Interval(n), AbsoluteErrorIntervalOp(error_range));
+}
+
+/** @returns a PointToIntervalOp for [n - numULP * ULP(n), n + numULP * ULP(n)] */
+function ULPIntervalOp(numULP) {
+ const op = {
+ impl: _ => {
+ return F32Interval.any();
+ },
+ };
+
+ if (isFiniteF32(numULP)) {
+ op.impl = n => {
+ assert(!Number.isNaN(n), `ULP error not defined for NaN`);
+
+ const ulp = oneULP(n);
+ const begin = n - numULP * ulp;
+ const end = n + numULP * ulp;
+
+ return toF32Interval([
+ Math.min(begin, flushSubnormalNumberF32(begin)),
+ Math.max(end, flushSubnormalNumberF32(end)),
+ ]);
+ };
+ }
+
+ return op;
+}
+
+/** @returns an interval of N * ULP around the point */
+export function ulpInterval(n, numULP) {
+ numULP = Math.abs(numULP);
+ return runPointToIntervalOp(toF32Interval(n), ULPIntervalOp(numULP));
+}
+
+const AbsIntervalOp = {
+ impl: n => {
+ return correctlyRoundedInterval(Math.abs(n));
+ },
+};
+
+/** Calculate an acceptance interval for abs(n) */
+export function absInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AbsIntervalOp);
+}
+
+const AcosIntervalOp = {
+ impl: limitPointToIntervalDomain(toF32Interval([-1.0, 1.0]), n => {
+ // acos(n) = atan2(sqrt(1.0 - n * n), n)
+ const y = sqrtInterval(subtractionInterval(1, multiplicationInterval(n, n)));
+ return atan2Interval(y, n);
+ }),
+};
+
+/** Calculate an acceptance interval for acos(n) */
+export function acosInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AcosIntervalOp);
+}
+
+/** All acceptance interval functions for acosh(x) */
+export const acoshIntervals = [acoshAlternativeInterval, acoshPrimaryInterval];
+
+const AcoshAlternativeIntervalOp = {
+ impl: x => {
+ // acosh(x) = log(x + sqrt((x + 1.0f) * (x - 1.0)))
+ const inner_value = multiplicationInterval(
+ additionInterval(x, 1.0),
+ subtractionInterval(x, 1.0)
+ );
+
+ const sqrt_value = sqrtInterval(inner_value);
+ return logInterval(additionInterval(x, sqrt_value));
+ },
+};
+
+/** Calculate an acceptance interval of acosh(x) using log(x + sqrt((x + 1.0f) * (x - 1.0))) */
+export function acoshAlternativeInterval(x) {
+ return runPointToIntervalOp(toF32Interval(x), AcoshAlternativeIntervalOp);
+}
+
+const AcoshPrimaryIntervalOp = {
+ impl: x => {
+ // acosh(x) = log(x + sqrt(x * x - 1.0))
+ const inner_value = subtractionInterval(multiplicationInterval(x, x), 1.0);
+ const sqrt_value = sqrtInterval(inner_value);
+ return logInterval(additionInterval(x, sqrt_value));
+ },
+};
+
+/** Calculate an acceptance interval of acosh(x) using log(x + sqrt(x * x - 1.0)) */
+export function acoshPrimaryInterval(x) {
+ return runPointToIntervalOp(toF32Interval(x), AcoshPrimaryIntervalOp);
+}
+
+const AdditionIntervalOp = {
+ impl: (x, y) => {
+ return correctlyRoundedInterval(x + y);
+ },
+};
+
+/** Calculate an acceptance interval of x + y */
+export function additionInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), AdditionIntervalOp);
+}
+
+const AsinIntervalOp = {
+ impl: limitPointToIntervalDomain(toF32Interval([-1.0, 1.0]), n => {
+ // asin(n) = atan2(n, sqrt(1.0 - n * n))
+ const x = sqrtInterval(subtractionInterval(1, multiplicationInterval(n, n)));
+ return atan2Interval(n, x);
+ }),
+};
+
+/** Calculate an acceptance interval for asin(n) */
+export function asinInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AsinIntervalOp);
+}
+
+const AsinhIntervalOp = {
+ impl: x => {
+ // asinh(x) = log(x + sqrt(x * x + 1.0))
+ const inner_value = additionInterval(multiplicationInterval(x, x), 1.0);
+ const sqrt_value = sqrtInterval(inner_value);
+ return logInterval(additionInterval(x, sqrt_value));
+ },
+};
+
+/** Calculate an acceptance interval of asinh(x) */
+export function asinhInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AsinhIntervalOp);
+}
+
+const AtanIntervalOp = {
+ impl: n => {
+ return ulpInterval(Math.atan(n), 4096);
+ },
+};
+
+/** Calculate an acceptance interval of atan(x) */
+export function atanInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AtanIntervalOp);
+}
+
+const Atan2IntervalOp = {
+ impl: limitBinaryToIntervalDomain(
+ {
+ // For atan2, there params are labelled (y, x), not (x, y), so domain.x is first parameter (y), and domain.y is
+ // the second parameter (x)
+ x: [
+ toF32Interval([kValue.f32.negative.min, kValue.f32.negative.max]),
+ toF32Interval([kValue.f32.positive.min, kValue.f32.positive.max]),
+ ],
+ // first param must be finite and normal
+ y: [toF32Interval([-(2 ** 126), -(2 ** -126)]), toF32Interval([2 ** -126, 2 ** 126])], // inherited from division
+ },
+ (y, x) => {
+ const atan_yx = Math.atan(y / x);
+ // x > 0, atan(y/x)
+ if (x > 0) {
+ return ulpInterval(atan_yx, 4096);
+ }
+
+ // x < 0, y > 0, atan(y/x) + π
+ if (y > 0) {
+ return ulpInterval(atan_yx + kValue.f32.positive.pi.whole, 4096);
+ }
+
+ // x < 0, y < 0, atan(y/x) - π
+ return ulpInterval(atan_yx - kValue.f32.positive.pi.whole, 4096);
+ }
+ ),
+
+ extrema: (y, x) => {
+ // There is discontinuity + undefined behaviour at y/x = 0 that will dominate the accuracy
+ if (y.contains(0)) {
+ if (x.contains(0)) {
+ return [toF32Interval(0), toF32Interval(0)];
+ }
+ return [toF32Interval(0), x];
+ }
+ return [y, x];
+ },
+};
+
+/** Calculate an acceptance interval of atan2(y, x) */
+export function atan2Interval(y, x) {
+ return runBinaryToIntervalOp(toF32Interval(y), toF32Interval(x), Atan2IntervalOp);
+}
+
+const AtanhIntervalOp = {
+ impl: n => {
+ // atanh(x) = log((1.0 + x) / (1.0 - x)) * 0.5
+ const numerator = additionInterval(1.0, n);
+ const denominator = subtractionInterval(1.0, n);
+ const log_interval = logInterval(divisionInterval(numerator, denominator));
+ return multiplicationInterval(log_interval, 0.5);
+ },
+};
+
+/** Calculate an acceptance interval of atanh(x) */
+export function atanhInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), AtanhIntervalOp);
+}
+
+const CeilIntervalOp = {
+ impl: n => {
+ return correctlyRoundedInterval(Math.ceil(n));
+ },
+};
+
+/** Calculate an acceptance interval of ceil(x) */
+export function ceilInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), CeilIntervalOp);
+}
+
+const ClampMedianIntervalOp = {
+ impl: (x, y, z) => {
+ return correctlyRoundedInterval(
+ // Default sort is string sort, so have to implement numeric comparison.
+ // Cannot use the b-a one liner, because that assumes no infinities.
+ [x, y, z].sort((a, b) => {
+ if (a < b) {
+ return -1;
+ }
+ if (a > b) {
+ return 1;
+ }
+ return 0;
+ })[1]
+ );
+ },
+};
+
+/** All acceptance interval functions for clamp(x, y, z) */
+export const clampIntervals = [clampMinMaxInterval, clampMedianInterval];
+
+/** Calculate an acceptance interval of clamp(x, y, z) via median(x, y, z) */
+export function clampMedianInterval(x, y, z) {
+ return runTernaryToIntervalOp(
+ toF32Interval(x),
+ toF32Interval(y),
+ toF32Interval(z),
+ ClampMedianIntervalOp
+ );
+}
+
+const ClampMinMaxIntervalOp = {
+ impl: (x, low, high) => {
+ return correctlyRoundedInterval(Math.min(Math.max(x, low), high));
+ },
+};
+
+/** Calculate an acceptance interval of clamp(x, high, low) via min(max(x, low), high) */
+export function clampMinMaxInterval(x, low, high) {
+ return runTernaryToIntervalOp(
+ toF32Interval(x),
+ toF32Interval(low),
+ toF32Interval(high),
+ ClampMinMaxIntervalOp
+ );
+}
+
+const CosIntervalOp = {
+ impl: limitPointToIntervalDomain(kNegPiToPiInterval, n => {
+ return absoluteErrorInterval(Math.cos(n), 2 ** -11);
+ }),
+};
+
+/** Calculate an acceptance interval of cos(x) */
+export function cosInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), CosIntervalOp);
+}
+
+const CoshIntervalOp = {
+ impl: n => {
+ // cosh(x) = (exp(x) + exp(-x)) * 0.5
+ const minus_n = negationInterval(n);
+ return multiplicationInterval(additionInterval(expInterval(n), expInterval(minus_n)), 0.5);
+ },
+};
+
+/** Calculate an acceptance interval of cosh(x) */
+export function coshInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), CoshIntervalOp);
+}
+
+const CrossIntervalOp = {
+ impl: (x, y) => {
+ assert(x.length === 3, `CrossIntervalOp received x with ${x.length} instead of 3`);
+ assert(y.length === 3, `CrossIntervalOp received y with ${y.length} instead of 3`);
+
+ // cross(x, y) = r, where
+ // r[0] = x[1] * y[2] - x[2] * y[1]
+ // r[1] = x[2] * y[0] - x[0] * y[2]
+ // r[2] = x[0] * y[1] - x[1] * y[0]
+
+ const r0 = subtractionInterval(
+ multiplicationInterval(x[1], y[2]),
+ multiplicationInterval(x[2], y[1])
+ );
+
+ const r1 = subtractionInterval(
+ multiplicationInterval(x[2], y[0]),
+ multiplicationInterval(x[0], y[2])
+ );
+
+ const r2 = subtractionInterval(
+ multiplicationInterval(x[0], y[1]),
+ multiplicationInterval(x[1], y[0])
+ );
+
+ return [r0, r1, r2];
+ },
+};
+
+export function crossInterval(x, y) {
+ assert(x.length === 3, `Cross is only defined for vec3`);
+ assert(y.length === 3, `Cross is only defined for vec3`);
+ return runVectorPairToVectorOp(toF32Vector(x), toF32Vector(y), CrossIntervalOp);
+}
+
+const DegreesIntervalOp = {
+ impl: n => {
+ return multiplicationInterval(n, 57.295779513082322865);
+ },
+};
+
+/** Calculate an acceptance interval of degrees(x) */
+export function degreesInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), DegreesIntervalOp);
+}
+
+const DistanceIntervalScalarOp = {
+ impl: (x, y) => {
+ return lengthInterval(subtractionInterval(x, y));
+ },
+};
+
+const DistanceIntervalVectorOp = {
+ impl: (x, y) => {
+ return lengthInterval(
+ runBinaryToIntervalOpComponentWise(toF32Vector(x), toF32Vector(y), SubtractionIntervalOp)
+ );
+ },
+};
+
+/** Calculate an acceptance interval of distance(x, y) */
+export function distanceInterval(x, y) {
+ if (x instanceof Array && y instanceof Array) {
+ assert(
+ x.length === y.length,
+ `distanceInterval requires both params to have the same number of elements`
+ );
+
+ return runVectorPairToIntervalOp(toF32Vector(x), toF32Vector(y), DistanceIntervalVectorOp);
+ } else if (!(x instanceof Array) && !(y instanceof Array)) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), DistanceIntervalScalarOp);
+ }
+ unreachable(
+ `distanceInterval requires both params to both the same type, either scalars or vectors`
+ );
+}
+
+const DivisionIntervalOp = {
+ impl: limitBinaryToIntervalDomain(
+ {
+ x: [toF32Interval([kValue.f32.negative.min, kValue.f32.positive.max])],
+ y: [toF32Interval([-(2 ** 126), -(2 ** -126)]), toF32Interval([2 ** -126, 2 ** 126])],
+ },
+ (x, y) => {
+ if (y === 0) {
+ return F32Interval.any();
+ }
+ return ulpInterval(x / y, 2.5);
+ }
+ ),
+
+ extrema: (x, y) => {
+ // division has a discontinuity at y = 0.
+ if (y.contains(0)) {
+ y = toF32Interval(0);
+ }
+ return [x, y];
+ },
+};
+
+/** Calculate an acceptance interval of x / y */
+export function divisionInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), DivisionIntervalOp);
+}
+
+const DotIntervalOp = {
+ impl: (x, y) => {
+ // dot(x, y) = sum of x[i] * y[i]
+ const multiplications = runBinaryToIntervalOpComponentWise(
+ toF32Vector(x),
+ toF32Vector(y),
+ MultiplicationIntervalOp
+ );
+
+ // vec2 doesn't require permutations, since a + b = b + a for floats
+ if (multiplications.length === 2) {
+ return additionInterval(multiplications[0], multiplications[1]);
+ }
+
+ // The spec does not state the ordering of summation, so all of the permutations are calculated and their results
+ // spanned, since addition of more then two floats is not transitive, i.e. a + b + c is not guaranteed to equal
+ // b + a + c
+ const permutations = calculatePermutations(multiplications);
+ return F32Interval.span(
+ ...permutations.map(p => p.reduce((prev, cur) => additionInterval(prev, cur)))
+ );
+ },
+};
+
+export function dotInterval(x, y) {
+ assert(x.length === y.length, `dot not defined for vectors with different lengths`);
+ return runVectorPairToIntervalOp(toF32Vector(x), toF32Vector(y), DotIntervalOp);
+}
+
+const ExpIntervalOp = {
+ impl: n => {
+ return ulpInterval(Math.exp(n), 3 + 2 * Math.abs(n));
+ },
+};
+
+/** Calculate an acceptance interval for exp(x) */
+export function expInterval(x) {
+ return runPointToIntervalOp(toF32Interval(x), ExpIntervalOp);
+}
+
+const Exp2IntervalOp = {
+ impl: n => {
+ return ulpInterval(Math.pow(2, n), 3 + 2 * Math.abs(n));
+ },
+};
+
+/** Calculate an acceptance interval for exp2(x) */
+export function exp2Interval(x) {
+ return runPointToIntervalOp(toF32Interval(x), Exp2IntervalOp);
+}
+
+/**
+ * Calculate the acceptance intervals for faceForward(x, y, z)
+ *
+ * faceForward(x, y, z) = select(-x, x, dot(z, y) < 0.0)
+ *
+ * This builtin selects from two discrete results (delta rounding/flushing), so
+ * the majority of the framework code is not appropriate, since the framework
+ * attempts to span results.
+ *
+ * Thus a bespoke implementation is used instead of
+ * defining a Op and running that through the framework.
+ */
+export function faceForwardIntervals(x, y, z) {
+ const x_vec = toF32Vector(x);
+ // Running vector through runPointToIntervalOpComponentWise to make sure that flushing/rounding is handled, since
+ // toF32Vector does not perform those operations.
+ const positive_x = runPointToIntervalOpComponentWise(x_vec, { impl: toF32Interval });
+ const negative_x = runPointToIntervalOpComponentWise(x_vec, NegationIntervalOp);
+
+ const dot_interval = dotInterval(z, y);
+
+ const results = [];
+
+ if (!dot_interval.isFinite()) {
+ // dot calculation went out of bounds
+ // Inserting undefine in the result, so that the test running framework is aware
+ // of this potential OOB.
+ // For const-eval tests, it means that the test case should be skipped,
+ // since the shader will fail to compile.
+ // For non-const-eval the undefined should be stripped out of the possible
+ // results.
+
+ results.push(undefined);
+ }
+
+ // Because the result of dot can be an interval, it might span across 0, thus
+ // it is possible that both -x and x are valid responses.
+ if (dot_interval.begin < 0 || dot_interval.end < 0) {
+ results.push(positive_x);
+ }
+
+ if (dot_interval.begin >= 0 || dot_interval.end >= 0) {
+ results.push(negative_x);
+ }
+
+ assert(
+ results.length > 0 || results.every(r => r === undefined),
+ `faceForwardInterval selected neither positive x or negative x for the result, this shouldn't be possible`
+ );
+
+ return results;
+}
+
+const FloorIntervalOp = {
+ impl: n => {
+ return correctlyRoundedInterval(Math.floor(n));
+ },
+};
+
+/** Calculate an acceptance interval of floor(x) */
+export function floorInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), FloorIntervalOp);
+}
+
+const FmaIntervalOp = {
+ impl: (x, y, z) => {
+ return additionInterval(multiplicationInterval(x, y), z);
+ },
+};
+
+/** Calculate an acceptance interval for fma(x, y, z) */
+export function fmaInterval(x, y, z) {
+ return runTernaryToIntervalOp(
+ toF32Interval(x),
+ toF32Interval(y),
+ toF32Interval(z),
+ FmaIntervalOp
+ );
+}
+
+const FractIntervalOp = {
+ impl: n => {
+ // fract(x) = x - floor(x) is defined in the spec.
+ // For people coming from a non-graphics background this will cause some unintuitive results. For example,
+ // fract(-1.1) is not 0.1 or -0.1, but instead 0.9.
+ // This is how other shading languages operate and allows for a desirable wrap around in graphics programming.
+ const result = subtractionInterval(n, floorInterval(n));
+ if (result.contains(1)) {
+ // Very small negative numbers can lead to catastrophic cancellation, thus calculating a fract of 1.0, which is
+ // technically not a fractional part, so some implementations clamp the result to next nearest number.
+ return F32Interval.span(result, toF32Interval(kValue.f32.positive.less_than_one));
+ }
+ return result;
+ },
+};
+
+/** Calculate an acceptance interval of fract(x) */
+export function fractInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), FractIntervalOp);
+}
+
+const InverseSqrtIntervalOp = {
+ impl: limitPointToIntervalDomain(kGreaterThanZeroInterval, n => {
+ return ulpInterval(1 / Math.sqrt(n), 2);
+ }),
+};
+
+/** Calculate an acceptance interval of inverseSqrt(x) */
+export function inverseSqrtInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), InverseSqrtIntervalOp);
+}
+
+const LdexpIntervalOp = {
+ impl: limitBinaryToIntervalDomain(
+ // Implementing SPIR-V's more restrictive domain until
+ // https://github.com/gpuweb/gpuweb/issues/3134 is resolved
+ {
+ x: [toF32Interval([kValue.f32.negative.min, kValue.f32.positive.max])],
+ y: [toF32Interval([-126, 128])],
+ },
+ (e1, e2) => {
+ // Though the spec says the result of ldexp(e1, e2) = e1 * 2 ^ e2, the
+ // accuracy is listed as correctly rounded to the true value, so the
+ // inheritance framework does not need to be invoked to determine bounds.
+ // Instead the value at a higher precision is calculated and passed to
+ // correctlyRoundedInterval.
+ const result = e1 * 2 ** e2;
+ if (Number.isNaN(result)) {
+ // Overflowed TS's number type, so definitely out of bounds for f32
+ return F32Interval.any();
+ }
+ return correctlyRoundedInterval(result);
+ }
+ ),
+};
+
+/** Calculate an acceptance interval of ldexp(e1, e2) */
+export function ldexpInterval(e1, e2) {
+ return roundAndFlushBinaryToInterval(e1, e2, LdexpIntervalOp);
+}
+
+const LengthIntervalScalarOp = {
+ impl: n => {
+ return sqrtInterval(multiplicationInterval(n, n));
+ },
+};
+
+const LengthIntervalVectorOp = {
+ impl: n => {
+ return sqrtInterval(dotInterval(n, n));
+ },
+};
+
+/** Calculate an acceptance interval of length(x) */
+export function lengthInterval(n) {
+ if (n instanceof Array) {
+ return runVectorToIntervalOp(toF32Vector(n), LengthIntervalVectorOp);
+ } else {
+ return runPointToIntervalOp(toF32Interval(n), LengthIntervalScalarOp);
+ }
+}
+
+const LogIntervalOp = {
+ impl: limitPointToIntervalDomain(kGreaterThanZeroInterval, n => {
+ if (n >= 0.5 && n <= 2.0) {
+ return absoluteErrorInterval(Math.log(n), 2 ** -21);
+ }
+ return ulpInterval(Math.log(n), 3);
+ }),
+};
+
+/** Calculate an acceptance interval of log(x) */
+export function logInterval(x) {
+ return runPointToIntervalOp(toF32Interval(x), LogIntervalOp);
+}
+
+const Log2IntervalOp = {
+ impl: limitPointToIntervalDomain(kGreaterThanZeroInterval, n => {
+ if (n >= 0.5 && n <= 2.0) {
+ return absoluteErrorInterval(Math.log2(n), 2 ** -21);
+ }
+ return ulpInterval(Math.log2(n), 3);
+ }),
+};
+
+/** Calculate an acceptance interval of log2(x) */
+export function log2Interval(x) {
+ return runPointToIntervalOp(toF32Interval(x), Log2IntervalOp);
+}
+
+const MaxIntervalOp = {
+ impl: (x, y) => {
+ return correctlyRoundedInterval(Math.max(x, y));
+ },
+};
+
+/** Calculate an acceptance interval of max(x, y) */
+export function maxInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), MaxIntervalOp);
+}
+
+const MinIntervalOp = {
+ impl: (x, y) => {
+ return correctlyRoundedInterval(Math.min(x, y));
+ },
+};
+
+/** Calculate an acceptance interval of min(x, y) */
+export function minInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), MinIntervalOp);
+}
+
+const MixImpreciseIntervalOp = {
+ impl: (x, y, z) => {
+ // x + (y - x) * z =
+ // x + t, where t = (y - x) * z
+ const t = multiplicationInterval(subtractionInterval(y, x), z);
+ return additionInterval(x, t);
+ },
+};
+
+/** All acceptance interval functions for mix(x, y, z) */
+export const mixIntervals = [mixImpreciseInterval, mixPreciseInterval];
+
+/** Calculate an acceptance interval of mix(x, y, z) using x + (y - x) * z */
+export function mixImpreciseInterval(x, y, z) {
+ return runTernaryToIntervalOp(
+ toF32Interval(x),
+ toF32Interval(y),
+ toF32Interval(z),
+ MixImpreciseIntervalOp
+ );
+}
+
+const MixPreciseIntervalOp = {
+ impl: (x, y, z) => {
+ // x * (1.0 - z) + y * z =
+ // t + s, where t = x * (1.0 - z), s = y * z
+ const t = multiplicationInterval(x, subtractionInterval(1.0, z));
+ const s = multiplicationInterval(y, z);
+ return additionInterval(t, s);
+ },
+};
+
+/** Calculate an acceptance interval of mix(x, y, z) using x * (1.0 - z) + y * z */
+export function mixPreciseInterval(x, y, z) {
+ return runTernaryToIntervalOp(
+ toF32Interval(x),
+ toF32Interval(y),
+ toF32Interval(z),
+ MixPreciseIntervalOp
+ );
+}
+
+/** Calculate an acceptance interval of modf(x) */
+export function modfInterval(n) {
+ const fract = correctlyRoundedInterval(n % 1.0);
+ const whole = correctlyRoundedInterval(n - (n % 1.0));
+ return { fract, whole };
+}
+
+const MultiplicationInnerOp = {
+ impl: (x, y) => {
+ return correctlyRoundedInterval(x * y);
+ },
+};
+
+const MultiplicationIntervalOp = {
+ impl: (x, y) => {
+ return roundAndFlushBinaryToInterval(x, y, MultiplicationInnerOp);
+ },
+};
+
+/** Calculate an acceptance interval of x * y */
+export function multiplicationInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), MultiplicationIntervalOp);
+}
+
+const NegationIntervalOp = {
+ impl: n => {
+ return correctlyRoundedInterval(-n);
+ },
+};
+
+/** Calculate an acceptance interval of -x */
+export function negationInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), NegationIntervalOp);
+}
+
+const NormalizeIntervalOp = {
+ impl: n => {
+ const length = lengthInterval(n);
+ return toF32Vector(n.map(e => divisionInterval(e, length)));
+ },
+};
+
+/** Calculate an acceptance interval of normalize(x) */
+export function normalizeInterval(n) {
+ return runVectorToVectorOp(toF32Vector(n), NormalizeIntervalOp);
+}
+
+const PowIntervalOp = {
+ // pow(x, y) has no explicit domain restrictions, but inherits the x <= 0
+ // domain restriction from log2(x). Invoking log2Interval(x) in impl will
+ // enforce this, so there is no need to wrap the impl call here.
+ impl: (x, y) => {
+ return exp2Interval(multiplicationInterval(y, log2Interval(x)));
+ },
+};
+
+/** Calculate an acceptance interval of pow(x, y) */
+export function powInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), PowIntervalOp);
+}
+
+// Once a full implementation of F16Interval exists, the correctlyRounded for
+// that can potentially be used instead of having a bespoke operation
+// implementation.
+const QuantizeToF16IntervalOp = {
+ impl: n => {
+ const rounded = correctlyRoundedF16(n);
+ const flushed = addFlushedIfNeededF16(rounded);
+ return F32Interval.span(...flushed.map(toF32Interval));
+ },
+};
+
+/** Calculate an acceptance interval of quanitizeToF16(x) */
+export function quantizeToF16Interval(n) {
+ return runPointToIntervalOp(toF32Interval(n), QuantizeToF16IntervalOp);
+}
+
+const RadiansIntervalOp = {
+ impl: n => {
+ return multiplicationInterval(n, 0.017453292519943295474);
+ },
+};
+
+/** Calculate an acceptance interval of radians(x) */
+export function radiansInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), RadiansIntervalOp);
+}
+
+const ReflectIntervalOp = {
+ impl: (x, y) => {
+ assert(
+ x.length === y.length,
+ `ReflectIntervalOp received x (${x}) and y (${y}) with different numbers of elements`
+ );
+
+ // reflect(x, y) = x - 2.0 * dot(x, y) * y
+ // = x - t * y, t = 2.0 * dot(x, y)
+ // x = incident vector
+ // y = normal of reflecting surface
+ const t = multiplicationInterval(2.0, dotInterval(x, y));
+ const rhs = multiplyVectorByScalar(y, t);
+ return runBinaryToIntervalOpComponentWise(toF32Vector(x), rhs, SubtractionIntervalOp);
+ },
+};
+
+/** Calculate an acceptance interval of reflect(x, y) */
+export function reflectInterval(x, y) {
+ assert(
+ x.length === y.length,
+ `reflect is only defined for vectors with the same number of elements`
+ );
+
+ return runVectorPairToVectorOp(toF32Vector(x), toF32Vector(y), ReflectIntervalOp);
+}
+
+/**
+ * Calculate acceptance interval vectors of reflect(i, s, r)
+ *
+ * refract is a singular function in the sense that it is the only builtin that
+ * takes in (F32Vector, F32Vector, F32) and returns F32Vector and is basically
+ * defined in terms of other functions.
+ *
+ * Instead of implementing all of the framework code to integrate it with its
+ * own operation type/etc, it instead has a bespoke implementation that is a
+ * composition of other builtin functions that use the framework.
+ */
+export function refractInterval(i, s, r) {
+ assert(
+ i.length === s.length,
+ `refract is only defined for vectors with the same number of elements`
+ );
+
+ const r_squared = multiplicationInterval(r, r);
+ const dot = dotInterval(s, i);
+ const dot_squared = multiplicationInterval(dot, dot);
+ const one_minus_dot_squared = subtractionInterval(1, dot_squared);
+ const k = subtractionInterval(1.0, multiplicationInterval(r_squared, one_minus_dot_squared));
+
+ if (!k.isFinite() || k.containsZeroOrSubnormals()) {
+ // There is a discontinuity at k == 0, due to sqrt(k) being calculated, so exiting early
+ return kAnyVector[toF32Vector(i).length];
+ }
+
+ if (k.end < 0.0) {
+ // if k is negative, then the zero vector is the valid response
+ return kZeroVector[toF32Vector(i).length];
+ }
+
+ const dot_times_r = multiplicationInterval(dot, r);
+ const k_sqrt = sqrtInterval(k);
+ const t = additionInterval(dot_times_r, k_sqrt); // t = r * dot(i, s) + sqrt(k)
+
+ const result = runBinaryToIntervalOpComponentWise(
+ multiplyVectorByScalar(i, r),
+ multiplyVectorByScalar(s, t),
+ SubtractionIntervalOp
+ );
+ // (i * r) - (s * t)
+ return result;
+}
+
+const RemainderIntervalOp = {
+ impl: (x, y) => {
+ // x % y = x - y * trunc(x/y)
+ return subtractionInterval(x, multiplicationInterval(y, truncInterval(divisionInterval(x, y))));
+ },
+};
+
+/** Calculate an acceptance interval for x % y */
+export function remainderInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), RemainderIntervalOp);
+}
+
+const RoundIntervalOp = {
+ impl: n => {
+ const k = Math.floor(n);
+ const diff_before = n - k;
+ const diff_after = k + 1 - n;
+ if (diff_before < diff_after) {
+ return correctlyRoundedInterval(k);
+ } else if (diff_before > diff_after) {
+ return correctlyRoundedInterval(k + 1);
+ }
+
+ // n is in the middle of two integers.
+ // The tie breaking rule is 'k if k is even, k + 1 if k is odd'
+ if (k % 2 === 0) {
+ return correctlyRoundedInterval(k);
+ }
+ return correctlyRoundedInterval(k + 1);
+ },
+};
+
+/** Calculate an acceptance interval of round(x) */
+export function roundInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), RoundIntervalOp);
+}
+
+/**
+ * Calculate an acceptance interval of saturate(n) as clamp(n, 0.0, 1.0)
+ *
+ * The definition of saturate is such that both possible implementations of
+ * clamp will return the same value, so arbitrarily picking the minmax version
+ * to use.
+ */
+export function saturateInterval(n) {
+ return runTernaryToIntervalOp(
+ toF32Interval(n),
+ toF32Interval(0.0),
+ toF32Interval(1.0),
+ ClampMinMaxIntervalOp
+ );
+}
+
+const SignIntervalOp = {
+ impl: n => {
+ if (n > 0.0) {
+ return correctlyRoundedInterval(1.0);
+ }
+ if (n < 0.0) {
+ return correctlyRoundedInterval(-1.0);
+ }
+
+ return correctlyRoundedInterval(0.0);
+ },
+};
+
+/** Calculate an acceptance interval of sin(x) */
+export function signInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), SignIntervalOp);
+}
+
+const SinIntervalOp = {
+ impl: limitPointToIntervalDomain(kNegPiToPiInterval, n => {
+ return absoluteErrorInterval(Math.sin(n), 2 ** -11);
+ }),
+};
+
+/** Calculate an acceptance interval of sin(x) */
+export function sinInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), SinIntervalOp);
+}
+
+const SinhIntervalOp = {
+ impl: n => {
+ // sinh(x) = (exp(x) - exp(-x)) * 0.5
+ const minus_n = negationInterval(n);
+ return multiplicationInterval(subtractionInterval(expInterval(n), expInterval(minus_n)), 0.5);
+ },
+};
+
+/** Calculate an acceptance interval of sinh(x) */
+export function sinhInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), SinhIntervalOp);
+}
+
+const SmoothStepOp = {
+ impl: (low, high, x) => {
+ // For clamp(foo, 0.0, 1.0) the different implementations of clamp provide
+ // the same value, so arbitrarily picking the minmax version to use.
+ // t = clamp((x - low) / (high - low), 0.0, 1.0)
+
+ const t = clampMedianInterval(
+ divisionInterval(subtractionInterval(x, low), subtractionInterval(high, low)),
+ 0.0,
+ 1.0
+ );
+ // Inherited from t * t * (3.0 - 2.0 * t)
+
+ return multiplicationInterval(
+ t,
+ multiplicationInterval(t, subtractionInterval(3.0, multiplicationInterval(2.0, t)))
+ );
+ },
+};
+
+/** Calculate an acceptance interval of smoothStep(low, high, x) */
+export function smoothStepInterval(low, high, x) {
+ return runTernaryToIntervalOp(
+ toF32Interval(low),
+ toF32Interval(high),
+ toF32Interval(x),
+ SmoothStepOp
+ );
+}
+
+const SqrtIntervalOp = {
+ impl: n => {
+ return divisionInterval(1.0, inverseSqrtInterval(n));
+ },
+};
+
+/** Calculate an acceptance interval of sqrt(x) */
+export function sqrtInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), SqrtIntervalOp);
+}
+
+const StepIntervalOp = {
+ impl: (edge, x) => {
+ if (edge <= x) {
+ return correctlyRoundedInterval(1.0);
+ }
+ return correctlyRoundedInterval(0.0);
+ },
+};
+
+/** Calculate an acceptance 'interval' for step(edge, x)
+ *
+ * step only returns two possible values, so its interval requires special
+ * interpretation in CTS tests.
+ * This interval will be one of four values: [0, 0], [0, 1], [1, 1] & [-∞, +∞].
+ * [0, 0] and [1, 1] indicate that the correct answer in point they encapsulate.
+ * [0, 1] should not be treated as a span, i.e. 0.1 is acceptable, but instead
+ * indicate either 0.0 or 1.0 are acceptable answers.
+ * [-∞, +∞] is treated as the any interval, since an undefined or infinite value was passed in.
+ */
+export function stepInterval(edge, x) {
+ return runBinaryToIntervalOp(toF32Interval(edge), toF32Interval(x), StepIntervalOp);
+}
+
+const SubtractionIntervalOp = {
+ impl: (x, y) => {
+ return correctlyRoundedInterval(x - y);
+ },
+};
+
+/** Calculate an acceptance interval of x - y */
+export function subtractionInterval(x, y) {
+ return runBinaryToIntervalOp(toF32Interval(x), toF32Interval(y), SubtractionIntervalOp);
+}
+
+const TanIntervalOp = {
+ impl: n => {
+ return divisionInterval(sinInterval(n), cosInterval(n));
+ },
+};
+
+/** Calculate an acceptance interval of tan(x) */
+export function tanInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), TanIntervalOp);
+}
+
+const TanhIntervalOp = {
+ impl: n => {
+ return divisionInterval(sinhInterval(n), coshInterval(n));
+ },
+};
+
+/** Calculate an acceptance interval of tanh(x) */
+export function tanhInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), TanhIntervalOp);
+}
+
+const TruncIntervalOp = {
+ impl: n => {
+ return correctlyRoundedInterval(Math.trunc(n));
+ },
+};
+
+/** Calculate an acceptance interval of trunc(x) */
+export function truncInterval(n) {
+ return runPointToIntervalOp(toF32Interval(n), TruncIntervalOp);
+}
+
+/**
+ * Once-allocated ArrayBuffer/views to avoid overhead of allocation when converting between numeric formats
+ *
+ * unpackData* is shared between all of the unpack*Interval functions, so to avoid re-entrancy problems, they should
+ * not call each other or themselves directly or indirectly.
+ */
+const unpackData = new ArrayBuffer(4);
+const unpackDataU32 = new Uint32Array(unpackData);
+const unpackDataU16 = new Uint16Array(unpackData);
+const unpackDataU8 = new Uint8Array(unpackData);
+const unpackDataI16 = new Int16Array(unpackData);
+const unpackDataI8 = new Int8Array(unpackData);
+const unpackDataF16 = new Float16Array(unpackData);
+
+/** Calculate an acceptance interval vector for unpack2x16float(x) */
+export function unpack2x16floatInterval(n) {
+ assert(
+ n >= kValue.u32.min && n <= kValue.u32.max,
+ 'unpack2x16floatInterval only accepts values on the bounds of u32'
+ );
+
+ unpackDataU32[0] = n;
+ if (unpackDataF16.some(f => !isFiniteF16(f))) {
+ return [F32Interval.any(), F32Interval.any()];
+ }
+
+ const result = [quantizeToF16Interval(unpackDataF16[0]), quantizeToF16Interval(unpackDataF16[1])];
+
+ if (result.some(r => !r.isFinite())) {
+ return [F32Interval.any(), F32Interval.any()];
+ }
+ return result;
+}
+
+const Unpack2x16snormIntervalOp = n => {
+ return maxInterval(divisionInterval(n, 32767), -1);
+};
+
+/** Calculate an acceptance interval vector for unpack2x16snorm(x) */
+export function unpack2x16snormInterval(n) {
+ assert(
+ n >= kValue.u32.min && n <= kValue.u32.max,
+ 'unpack2x16snormInterval only accepts values on the bounds of u32'
+ );
+
+ unpackDataU32[0] = n;
+ return [Unpack2x16snormIntervalOp(unpackDataI16[0]), Unpack2x16snormIntervalOp(unpackDataI16[1])];
+}
+
+const Unpack2x16unormIntervalOp = n => {
+ return divisionInterval(n, 65535);
+};
+
+/** Calculate an acceptance interval vector for unpack2x16unorm(x) */
+export function unpack2x16unormInterval(n) {
+ assert(
+ n >= kValue.u32.min && n <= kValue.u32.max,
+ 'unpack2x16unormInterval only accepts values on the bounds of u32'
+ );
+
+ unpackDataU32[0] = n;
+ return [Unpack2x16unormIntervalOp(unpackDataU16[0]), Unpack2x16unormIntervalOp(unpackDataU16[1])];
+}
+
+const Unpack4x8snormIntervalOp = n => {
+ return maxInterval(divisionInterval(n, 127), -1);
+};
+
+/** Calculate an acceptance interval vector for unpack4x8snorm(x) */
+export function unpack4x8snormInterval(n) {
+ assert(
+ n >= kValue.u32.min && n <= kValue.u32.max,
+ 'unpack4x8snormInterval only accepts values on the bounds of u32'
+ );
+
+ unpackDataU32[0] = n;
+ return [
+ Unpack4x8snormIntervalOp(unpackDataI8[0]),
+ Unpack4x8snormIntervalOp(unpackDataI8[1]),
+ Unpack4x8snormIntervalOp(unpackDataI8[2]),
+ Unpack4x8snormIntervalOp(unpackDataI8[3]),
+ ];
+}
+
+const Unpack4x8unormIntervalOp = n => {
+ return divisionInterval(n, 255);
+};
+
+/** Calculate an acceptance interval vector for unpack4x8unorm(x) */
+export function unpack4x8unormInterval(n) {
+ assert(
+ n >= kValue.u32.min && n <= kValue.u32.max,
+ 'unpack4x8unormInterval only accepts values on the bounds of u32'
+ );
+
+ unpackDataU32[0] = n;
+ return [
+ Unpack4x8unormIntervalOp(unpackDataU8[0]),
+ Unpack4x8unormIntervalOp(unpackDataU8[1]),
+ Unpack4x8unormIntervalOp(unpackDataU8[2]),
+ Unpack4x8unormIntervalOp(unpackDataU8[3]),
+ ];
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js
new file mode 100644
index 0000000000..b95d7d7b4c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/math.js
@@ -0,0 +1,949 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../common/util/util.js';
+import { Float16Array } from '../../external/petamoriken/float16/float16.js';
+import { kBit, kValue } from './constants.js';
+import {
+ f16,
+ f16Bits,
+ f32,
+ f32Bits,
+ floatBitsToNumber,
+ i32,
+ kFloat16Format,
+ kFloat32Format,
+ u32,
+} from './conversion.js';
+
+/**
+ * A multiple of 8 guaranteed to be way too large to allocate (just under 8 pebibytes).
+ * This is a "safe" integer (ULP <= 1.0) very close to MAX_SAFE_INTEGER.
+ *
+ * Note: allocations of this size are likely to exceed limitations other than just the system's
+ * physical memory, so test cases are also needed to try to trigger "true" OOM.
+ */
+export const kMaxSafeMultipleOf8 = Number.MAX_SAFE_INTEGER - 7;
+
+/** Round `n` up to the next multiple of `alignment` (inclusive). */
+// MAINTENANCE_TODO: Rename to `roundUp`
+export function align(n, alignment) {
+ assert(Number.isInteger(n) && n >= 0, 'n must be a non-negative integer');
+ assert(Number.isInteger(alignment) && alignment > 0, 'alignment must be a positive integer');
+ return Math.ceil(n / alignment) * alignment;
+}
+
+/** Round `n` down to the next multiple of `alignment` (inclusive). */
+export function roundDown(n, alignment) {
+ assert(Number.isInteger(n) && n >= 0, 'n must be a non-negative integer');
+ assert(Number.isInteger(alignment) && alignment > 0, 'alignment must be a positive integer');
+ return Math.floor(n / alignment) * alignment;
+}
+
+/** Clamp a number to the provided range. */
+export function clamp(n, { min, max }) {
+ assert(max >= min);
+ return Math.min(Math.max(n, min), max);
+}
+
+/** @returns 0 if |val| is a subnormal f32 number, otherwise returns |val| */
+export function flushSubnormalNumberF32(val) {
+ return isSubnormalNumberF32(val) ? 0 : val;
+}
+
+/** @returns 0 if |val| is a subnormal f32 number, otherwise returns |val| */
+export function flushSubnormalScalarF32(val) {
+ return isSubnormalScalarF32(val) ? f32(0) : val;
+}
+
+/**
+ * @returns true if |val| is a subnormal f32 number, otherwise returns false
+ * 0 is considered a non-subnormal number by this function.
+ */
+export function isSubnormalScalarF32(val) {
+ if (val.type.kind !== 'f32') {
+ return false;
+ }
+
+ if (val === f32(0)) {
+ return false;
+ }
+
+ const u32_val = new Uint32Array(new Float32Array([val.value.valueOf()]).buffer)[0];
+ return (u32_val & 0x7f800000) === 0;
+}
+
+/** U/** @returns if number is within subnormal range of f32 */
+export function isSubnormalNumberF32(n) {
+ return n > kValue.f32.negative.max && n < kValue.f32.positive.min;
+}
+
+/** @returns if number is in the finite range of f32 */
+export function isFiniteF32(n) {
+ return n >= kValue.f32.negative.min && n <= kValue.f32.positive.max;
+}
+
+/** @returns 0 if |val| is a subnormal f16 number, otherwise returns |val| */
+export function flushSubnormalNumberF16(val) {
+ return isSubnormalNumberF16(val) ? 0 : val;
+}
+
+/** @returns 0 if |val| is a subnormal f16 number, otherwise returns |val| */
+export function flushSubnormalScalarF16(val) {
+ return isSubnormalScalarF16(val) ? f16(0) : val;
+}
+
+/**
+ * @returns true if |val| is a subnormal f16 number, otherwise returns false
+ * 0 is considered a non-subnormal number by this function.
+ */
+export function isSubnormalScalarF16(val) {
+ if (val.type.kind !== 'f16') {
+ return false;
+ }
+
+ if (val === f16(0)) {
+ return false;
+ }
+
+ const u16_val = new Uint16Array(new Float16Array([val.value.valueOf()]).buffer)[0];
+ return (u16_val & 0x7f800000) === 0;
+}
+
+/** @returns if number is within subnormal range of f16 */
+export function isSubnormalNumberF16(n) {
+ return n > kValue.f16.negative.max && n < kValue.f16.positive.min;
+}
+
+/** @returns if number is in the finite range of f16 */
+export function isFiniteF16(n) {
+ return n >= kValue.f16.negative.min && n <= kValue.f16.positive.max;
+}
+
+/** Should FTZ occur during calculations or not */
+
+/**
+ * @returns the next f32 value after |val|,
+ * towards +inf if |dir| is true, otherwise towards -inf.
+
+ * If |mpode| is 'flush', all subnormal values will be flushed to 0,
+ * before processing and for -/+0 the nextAfterF32 will be the closest normal in
+ * the correct direction.
+
+ * If |mode| is 'no-flush', the next subnormal will be calculated when appropriate,
+ * and for -/+0 the nextAfterF32 will be the closest subnormal in the correct
+ * direction.
+ *
+ * val needs to be in [min f32, max f32]
+ */
+export function nextAfterF32(val, dir = true, mode) {
+ if (Number.isNaN(val)) {
+ return f32Bits(kBit.f32.nan.positive.s);
+ }
+
+ if (val === Number.POSITIVE_INFINITY) {
+ return f32Bits(kBit.f32.infinity.positive);
+ }
+
+ if (val === Number.NEGATIVE_INFINITY) {
+ return f32Bits(kBit.f32.infinity.negative);
+ }
+
+ assert(
+ val <= kValue.f32.positive.max && val >= kValue.f32.negative.min,
+ `${val} is not in the range of float32`
+ );
+
+ val = mode === 'flush' ? flushSubnormalNumberF32(val) : val;
+
+ // -/+0 === 0 returns true
+ if (val === 0) {
+ if (dir) {
+ return mode === 'flush'
+ ? f32Bits(kBit.f32.positive.min)
+ : f32Bits(kBit.f32.subnormal.positive.min);
+ } else {
+ return mode === 'flush'
+ ? f32Bits(kBit.f32.negative.max)
+ : f32Bits(kBit.f32.subnormal.negative.max);
+ }
+ }
+
+ const converted = new Float32Array([val])[0];
+ let u32_result;
+ if (val === converted) {
+ // val is expressible precisely as a float32
+ u32_result = new Uint32Array(new Float32Array([val]).buffer)[0];
+ const is_positive = (u32_result & 0x80000000) === 0;
+ if (dir === is_positive) {
+ u32_result += 1;
+ } else {
+ u32_result -= 1;
+ }
+ } else {
+ // val had to be rounded to be expressed as a float32
+ if (dir === converted > val) {
+ // Rounding was in the direction requested
+ u32_result = new Uint32Array(new Float32Array([converted]).buffer)[0];
+ } else {
+ // Round was opposite of the direction requested, so need nextAfterF32 in the requested direction.
+ // This will not recurse since converted is guaranteed to be a float32 due to the conversion above.
+ const next = nextAfterF32(converted, dir, mode).value.valueOf();
+ u32_result = new Uint32Array(new Float32Array([next]).buffer)[0];
+ }
+ }
+
+ // Checking for overflow
+ if ((u32_result & 0x7f800000) === 0x7f800000) {
+ if (dir) {
+ return f32Bits(kBit.f32.infinity.positive);
+ } else {
+ return f32Bits(kBit.f32.infinity.negative);
+ }
+ }
+
+ const f32_result = f32Bits(u32_result);
+ return mode === 'flush' ? flushSubnormalScalarF32(f32_result) : f32_result;
+}
+
+/**
+ * @returns the next f16 value after |val|,
+ * towards +inf if |dir| is true, otherwise towards -inf.
+ *
+ * If |mode| is true, all subnormal values will be flushed to 0,
+ * before processing, and for -/+0 the nextAfterF16 will be the closest normal
+ * in the correct direction
+ *
+ * If |mode| is false, the next subnormal will be calculated when appropriate,
+ * and for -/+0 the nextAfterF16 will be the closest subnormal in the correct
+ * direction.
+ *
+ * val needs to be in [min f16, max f16]
+ */
+export function nextAfterF16(val, dir = true, mode) {
+ if (Number.isNaN(val)) {
+ return f16Bits(kBit.f16.nan.positive.s);
+ }
+
+ if (val === Number.POSITIVE_INFINITY) {
+ return f16Bits(kBit.f16.infinity.positive);
+ }
+
+ if (val === Number.NEGATIVE_INFINITY) {
+ return f16Bits(kBit.f16.infinity.negative);
+ }
+
+ assert(
+ val <= kValue.f16.positive.max && val >= kValue.f16.negative.min,
+ `${val} is not in the range of float16`
+ );
+
+ val = mode === 'flush' ? flushSubnormalNumberF16(val) : val;
+
+ // -/+0 === 0 returns true
+ if (val === 0) {
+ if (dir) {
+ return mode === 'flush'
+ ? f16Bits(kBit.f16.positive.min)
+ : f16Bits(kBit.f16.subnormal.positive.min);
+ } else {
+ return mode === 'flush'
+ ? f16Bits(kBit.f16.negative.max)
+ : f16Bits(kBit.f16.subnormal.negative.max);
+ }
+ }
+
+ const converted = new Float16Array([val])[0];
+ let u16_result;
+ if (val === converted) {
+ // val is expressible precisely as a float16
+ u16_result = new Uint16Array(new Float16Array([val]).buffer)[0];
+ const is_positive = (u16_result & 0x8000) === 0;
+ if (dir === is_positive) {
+ u16_result += 1;
+ } else {
+ u16_result -= 1;
+ }
+ } else {
+ // val had to be rounded to be expressed as a float16
+ if (dir === converted > val) {
+ // Rounding was in the direction requested
+ u16_result = new Uint16Array(new Float16Array([converted]).buffer)[0];
+ } else {
+ // Round was opposite of the direction requested, so need nextAfterF16 in the requested direction.
+ // This will not recurse since converted is guaranteed to be a float16 due to the conversion above.
+ const next = nextAfterF16(converted, dir, mode).value.valueOf();
+ u16_result = new Uint16Array(new Float16Array([next]).buffer)[0];
+ }
+ }
+
+ // Checking for overflow
+ if ((u16_result & 0x7f800000) === 0x7f800000) {
+ if (dir) {
+ return f16Bits(kBit.f16.infinity.positive);
+ } else {
+ return f16Bits(kBit.f16.infinity.negative);
+ }
+ }
+
+ const f16_result = f16Bits(u16_result);
+ return mode === 'flush' ? flushSubnormalScalarF16(f16_result) : f16_result;
+}
+
+/**
+ * @returns ulp(x), the unit of least precision for a specific number as a 32-bit float
+ *
+ * ulp(x) is the distance between the two floating point numbers nearest x.
+ * This value is also called unit of last place, ULP, and 1 ULP.
+ * See the WGSL spec and http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2005/RR2005-09.pdf
+ * for a more detailed/nuanced discussion of the definition of ulp(x).
+ *
+ * @param target number to calculate ULP for
+ * @param mode should FTZ occuring during calculation or not
+ */
+export function oneULP(target, mode = 'flush') {
+ if (Number.isNaN(target)) {
+ return Number.NaN;
+ }
+
+ target = mode === 'flush' ? flushSubnormalNumberF32(target) : target;
+
+ // For values at the edge of the range or beyond ulp(x) is defined as the distance between the two nearest
+ // f32 representable numbers to the appropriate edge.
+ if (target === Number.POSITIVE_INFINITY || target >= kValue.f32.positive.max) {
+ return kValue.f32.positive.max - kValue.f32.positive.nearest_max;
+ } else if (target === Number.NEGATIVE_INFINITY || target <= kValue.f32.negative.min) {
+ return kValue.f32.negative.nearest_min - kValue.f32.negative.min;
+ }
+
+ // ulp(x) is min(after - before), where
+ // before <= x <= after
+ // before =/= after
+ // before and after are f32 representable
+ const before = nextAfterF32(target, false, mode).value.valueOf();
+ const after = nextAfterF32(target, true, mode).value.valueOf();
+ const converted = new Float32Array([target])[0];
+ if (converted === target) {
+ // |target| is f32 representable, so either before or after will be x
+ return Math.min(target - before, after - target);
+ } else {
+ // |target| is not f32 representable so taking distance of neighbouring f32s.
+ return after - before;
+ }
+}
+
+/**
+ * Calculate the valid roundings when quantizing to 32-bit floats
+ *
+ * TS/JS's number type is internally a f64, so quantization needs to occur when
+ * converting to f32 for WGSL. WGSL does not specify a specific rounding mode,
+ * so if a number is not precisely representable in 32-bits, but in the
+ * range, there are two possible valid quantizations. If it is precisely
+ * representable, there is only one valid quantization. This function calculates
+ * the valid roundings and returns them in an array.
+ *
+ * This function does not consider flushing mode, so subnormals are maintained.
+ * The caller is responsible to flushing before and after as appropriate.
+ *
+ * Out of range values return the appropriate infinity and edge value.
+ *
+ * @param n number to be quantized
+ * @returns all of the acceptable roundings for quantizing to 32-bits in
+ * ascending order.
+ */
+export function correctlyRoundedF32(n) {
+ assert(!Number.isNaN(n), `correctlyRoundedF32 not defined for NaN`);
+ // Above f32 range
+ if (n === Number.POSITIVE_INFINITY || n > kValue.f32.positive.max) {
+ return [kValue.f32.positive.max, Number.POSITIVE_INFINITY];
+ }
+
+ // Below f32 range
+ if (n === Number.NEGATIVE_INFINITY || n < kValue.f32.negative.min) {
+ return [Number.NEGATIVE_INFINITY, kValue.f32.negative.min];
+ }
+
+ const n_32 = new Float32Array([n])[0];
+ const converted = n_32;
+ if (n === converted) {
+ // n is precisely expressible as a f32, so should not be rounded
+ return [n];
+ }
+
+ if (converted > n) {
+ // n_32 rounded towards +inf, so is after n
+ const other = nextAfterF32(n_32, false, 'no-flush').value;
+ return [other, converted];
+ } else {
+ // n_32 rounded towards -inf, so is before n
+ const other = nextAfterF32(n_32, true, 'no-flush').value;
+ return [converted, other];
+ }
+}
+
+/**
+ * Calculate the valid roundings when quantizing to 16-bit floats
+ *
+ * TS/JS's number type is internally a f64, so quantization needs to occur when
+ * converting to f16 for WGSL. WGSL does not specify a specific rounding mode,
+ * so if a number is not precisely representable in 16-bits, but in the
+ * range, there are two possible valid quantizations. If it is precisely
+ * representable, there is only one valid quantization. This function calculates
+ * the valid roundings and returns them in an array.
+ *
+ * This function does not consider flushing mode, so subnormals are maintained.
+ * The caller is responsible to flushing before and after as appropriate.
+ *
+ * Out of range values return the appropriate infinity and edge value.
+ *
+ * @param n number to be quantized
+ * @returns all of the acceptable roundings for quantizing to 16-bits in
+ * ascending order.
+ */
+export function correctlyRoundedF16(n) {
+ assert(!Number.isNaN(n), `correctlyRoundedF16 not defined for NaN`);
+ // Above f16 range
+ if (n === Number.POSITIVE_INFINITY || n > kValue.f16.positive.max) {
+ return [kValue.f16.positive.max, Number.POSITIVE_INFINITY];
+ }
+
+ // Below f16 range
+ if (n === Number.NEGATIVE_INFINITY || n < kValue.f16.negative.min) {
+ return [Number.NEGATIVE_INFINITY, kValue.f16.negative.min];
+ }
+
+ const n_16 = new Float16Array([n])[0];
+ const converted = n_16;
+ if (n === converted) {
+ // n is precisely expressible as a f16, so should not be rounded
+ return [n];
+ }
+
+ if (converted > n) {
+ // n_16 rounded towards +inf, so is after n
+ const other = nextAfterF16(n_16, false, 'no-flush').value;
+ return [other, converted];
+ } else {
+ // n_16 rounded towards -inf, so is before n
+ const other = nextAfterF16(n_16, true, 'no-flush').value;
+ return [converted, other];
+ }
+}
+
+/**
+ * Calculates the linear interpolation between two values of a given fractional.
+ *
+ * If |t| is 0, |a| is returned, if |t| is 1, |b| is returned, otherwise
+ * interpolation/extrapolation equivalent to a + t(b - a) is performed.
+ *
+ * Numerical stable version is adapted from http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0811r2.html
+ */
+export function lerp(a, b, t) {
+ if (!Number.isFinite(a) || !Number.isFinite(b)) {
+ return Number.NaN;
+ }
+
+ if ((a <= 0.0 && b >= 0.0) || (a >= 0.0 && b <= 0.0)) {
+ return t * b + (1 - t) * a;
+ }
+
+ if (t === 1.0) {
+ return b;
+ }
+
+ const x = a + t * (b - a);
+ return t > 1.0 === b > a ? Math.max(b, x) : Math.min(b, x);
+}
+
+/** @returns a linear increasing range of numbers. */
+export function linearRange(a, b, num_steps) {
+ if (num_steps <= 0) {
+ return Array();
+ }
+
+ // Avoid division by 0
+ if (num_steps === 1) {
+ return [a];
+ }
+
+ return Array.from(Array(num_steps).keys()).map(i => lerp(a, b, i / (num_steps - 1)));
+}
+
+/**
+ * @returns a non-linear increasing range of numbers, with a bias towards the beginning.
+ *
+ * Generates a linear range on [0,1] with |num_steps|, then squares all the values to make the curve be quadratic,
+ * thus biasing towards 0, but remaining on the [0, 1] range.
+ * This biased range is then scaled to the desired range using lerp.
+ * Different curves could be generated by changing c, where greater values of c will bias more towards 0.
+ */
+export function biasedRange(a, b, num_steps) {
+ const c = 2;
+ if (num_steps <= 0) {
+ return Array();
+ }
+
+ // Avoid division by 0
+ if (num_steps === 1) {
+ return [a];
+ }
+
+ return Array.from(Array(num_steps).keys()).map(i => lerp(a, b, Math.pow(i / (num_steps - 1), c)));
+}
+
+/**
+ * @returns an ascending sorted array of numbers spread over the entire range of 32-bit floats
+ *
+ * Numbers are divided into 4 regions: negative normals, negative subnormals, positive subnormals & positive normals.
+ * Zero is included.
+ *
+ * Numbers are generated via taking a linear spread of the bit field representations of the values in each region. This
+ * means that number of precise f32 values between each returned value in a region should be about the same. This allows
+ * for a wide range of magnitudes to be generated, instead of being extremely biased towards the edges of the f32 range.
+ *
+ * This function is intended to provide dense coverage of the f32 range, for a minimal list of values to use to cover
+ * f32 behaviour, use sparseF32Range instead.
+ *
+ * @param counts structure param with 4 entries indicating the number of entries to be generated each region, entries
+ * must be 0 or greater.
+ */
+export function fullF32Range(counts = { pos_sub: 10, pos_norm: 50 }) {
+ counts.neg_norm = counts.neg_norm === undefined ? counts.pos_norm : counts.neg_norm;
+ counts.neg_sub = counts.neg_sub === undefined ? counts.pos_sub : counts.neg_sub;
+
+ // Generating bit fields first and then converting to f32, so that the spread across the possible f32 values is more
+ // even. Generating against the bounds of f32 values directly results in the values being extremely biased towards the
+ // extremes, since they are so much larger.
+ const bit_fields = [
+ ...linearRange(kBit.f32.negative.min, kBit.f32.negative.max, counts.neg_norm),
+ ...linearRange(
+ kBit.f32.subnormal.negative.min,
+ kBit.f32.subnormal.negative.max,
+ counts.neg_sub
+ ),
+
+ 0,
+ ...linearRange(
+ kBit.f32.subnormal.positive.min,
+ kBit.f32.subnormal.positive.max,
+ counts.pos_sub
+ ),
+
+ ...linearRange(kBit.f32.positive.min, kBit.f32.positive.max, counts.pos_norm),
+ ].map(Math.trunc);
+ return bit_fields.map(hexToF32);
+}
+
+/**
+ * @returns an ascending sorted array of numbers.
+ *
+ * The numbers returned are based on the `full32Range` as described above. The difference comes depending
+ * on the `source` parameter. If the `source` is `const` then the numbers will be restricted to be
+ * in the range `[low, high]`. This allows filtering out a set of `f32` values which are invalid for
+ * const-evaluation but are needed to test the non-const implementation.
+ *
+ * @param source the input source for the test. If the `source` is `const` then the return will be filtered
+ * @param low the lowest f32 value to permit when filtered
+ * @param high the highest f32 value to permit when filtered
+ */
+export function sourceFilteredF32Range(source, low, high) {
+ return fullF32Range().filter(x => source !== 'const' || (x >= low && x <= high));
+}
+
+/**
+ * @returns an ascending sorted array of numbers spread over the entire range of 16-bit floats
+ *
+ * Numbers are divided into 4 regions: negative normals, negative subnormals, positive subnormals & positive normals.
+ * Zero is included.
+ *
+ * Numbers are generated via taking a linear spread of the bit field representations of the values in each region. This
+ * means that number of precise f16 values between each returned value in a region should be about the same. This allows
+ * for a wide range of magnitudes to be generated, instead of being extremely biased towards the edges of the f16 range.
+ *
+ * This function is intended to provide dense coverage of the f16 range, for a minimal list of values to use to cover
+ * f16 behaviour, use sparseF16Range instead.
+ *
+ * @param counts structure param with 4 entries indicating the number of entries to be generated each region, entries
+ * must be 0 or greater.
+ */
+export function fullF16Range(counts = { pos_sub: 10, pos_norm: 50 }) {
+ counts.neg_norm = counts.neg_norm === undefined ? counts.pos_norm : counts.neg_norm;
+ counts.neg_sub = counts.neg_sub === undefined ? counts.pos_sub : counts.neg_sub;
+
+ // Generating bit fields first and then converting to f16, so that the spread across the possible f16 values is more
+ // even. Generating against the bounds of f16 values directly results in the values being extremely biased towards the
+ // extremes, since they are so much larger.
+ const bit_fields = [
+ ...linearRange(kBit.f16.negative.min, kBit.f16.negative.max, counts.neg_norm),
+ ...linearRange(
+ kBit.f16.subnormal.negative.min,
+ kBit.f16.subnormal.negative.max,
+ counts.neg_sub
+ ),
+
+ 0,
+ ...linearRange(
+ kBit.f16.subnormal.positive.min,
+ kBit.f16.subnormal.positive.max,
+ counts.pos_sub
+ ),
+
+ ...linearRange(kBit.f16.positive.min, kBit.f16.positive.max, counts.pos_norm),
+ ].map(Math.trunc);
+ return bit_fields.map(hexToF16);
+}
+
+/**
+ * @returns an ascending sorted array of numbers spread over the entire range of 32-bit signed ints
+ *
+ * Numbers are divided into 2 regions: negatives, and positives, with their spreads biased towards 0
+ * Zero is included in range.
+ *
+ * @param counts structure param with 2 entries indicating the number of entries to be generated each region, values must be 0 or greater.
+ */
+export function fullI32Range(counts = { positive: 50 }) {
+ counts.negative = counts.negative === undefined ? counts.positive : counts.negative;
+ return [
+ ...biasedRange(kValue.i32.negative.min, -1, counts.negative),
+ 0,
+ ...biasedRange(1, kValue.i32.positive.max, counts.positive),
+ ].map(Math.trunc);
+}
+
+/** Short list of u32 values of interest to test against */
+const kInterestingU32Values = [0, 1, kValue.u32.max / 2, kValue.u32.max];
+
+/** @returns minimal u32 values that cover the entire range of u32 behaviours
+ *
+ * This is used instead of fullU32Range when the number of test cases being
+ * generated is a super linear function of the length of u32 values which is
+ * leading to time outs.
+ */
+export function sparseU32Range() {
+ return kInterestingU32Values;
+}
+
+const kVectorU32Values = {
+ 2: kInterestingU32Values.flatMap(f => [
+ [f, 1],
+ [1, f],
+ ]),
+
+ 3: kInterestingU32Values.flatMap(f => [
+ [f, 1, 2],
+ [1, f, 2],
+ [1, 2, f],
+ ]),
+
+ 4: kInterestingU32Values.flatMap(f => [
+ [f, 1, 2, 3],
+ [1, f, 2, 3],
+ [1, 2, f, 3],
+ [1, 2, 3, f],
+ ]),
+};
+
+/**
+ * Returns set of vectors, indexed by dimension containing interesting u32
+ * values.
+ *
+ * The tests do not do the simple option for coverage of computing the cartesian
+ * product of all of the interesting u32 values N times for vecN tests,
+ * because that creates a huge number of tests for vec3 and vec4, leading to
+ * time outs.
+ *
+ * Instead they insert the interesting u32 values into each location of the
+ * vector to get a spread of testing over the entire range. This reduces the
+ * number of cases being run substantially, but maintains coverage.
+ */
+export function vectorU32Range(dim) {
+ assert(dim === 2 || dim === 3 || dim === 4, 'vectorU32Range only accepts dimensions 2, 3, and 4');
+ return kVectorU32Values[dim];
+}
+
+/**
+ * @returns an ascending sorted array of numbers spread over the entire range of 32-bit unsigned ints
+ *
+ * Numbers are biased towards 0, and 0 is included in the range.
+ *
+ * @param count number of entries to include in the range, in addition to 0, must be greater than 0, defaults to 50
+ */
+export function fullU32Range(count = 50) {
+ return [0, ...biasedRange(1, kValue.u32.max, count)].map(Math.trunc);
+}
+
+/** Short list of f32 values of interest to test against */
+const kInterestingF32Values = [
+ kValue.f32.negative.min,
+ -10.0,
+ -1.0,
+ kValue.f32.negative.max,
+ kValue.f32.subnormal.negative.min,
+ kValue.f32.subnormal.negative.max,
+ 0.0,
+ kValue.f32.subnormal.positive.min,
+ kValue.f32.subnormal.positive.max,
+ kValue.f32.positive.min,
+ 1.0,
+ 10.0,
+ kValue.f32.positive.max,
+];
+
+/** @returns minimal f32 values that cover the entire range of f32 behaviours
+ *
+ * Has specially selected values that cover edge cases, normals, and subnormals.
+ * This is used instead of fullF32Range when the number of test cases being
+ * generated is a super linear function of the length of f32 values which is
+ * leading to time outs.
+ *
+ * These values have been chosen to attempt to test the widest range of f32
+ * behaviours in the lowest number of entries, so may potentially miss function
+ * specific values of interest. If there are known values of interest they
+ * should be appended to this list in the test generation code.
+ */
+export function sparseF32Range() {
+ return kInterestingF32Values;
+}
+
+const kVectorF32Values = {
+ 2: kInterestingF32Values.flatMap(f => [
+ [f, 1.0],
+ [1.0, f],
+ [f, -1.0],
+ [-1.0, f],
+ ]),
+
+ 3: kInterestingF32Values.flatMap(f => [
+ [f, 1.0, 2.0],
+ [1.0, f, 2.0],
+ [1.0, 2.0, f],
+ [f, -1.0, -2.0],
+ [-1.0, f, -2.0],
+ [-1.0, -2.0, f],
+ ]),
+
+ 4: kInterestingF32Values.flatMap(f => [
+ [f, 1.0, 2.0, 3.0],
+ [1.0, f, 2.0, 3.0],
+ [1.0, 2.0, f, 3.0],
+ [1.0, 2.0, 3.0, f],
+ [f, -1.0, -2.0, -3.0],
+ [-1.0, f, -2.0, -3.0],
+ [-1.0, -2.0, f, -3.0],
+ [-1.0, -2.0, -3.0, f],
+ ]),
+};
+
+/**
+ * Returns set of vectors, indexed by dimension containing interesting float
+ * values.
+ *
+ * The tests do not do the simple option for coverage of computing the cartesian
+ * product of all of the interesting float values N times for vecN tests,
+ * because that creates a huge number of tests for vec3 and vec4, leading to
+ * time outs.
+ *
+ * Instead they insert the interesting f32 values into each location of the
+ * vector to get a spread of testing over the entire range. This reduces the
+ * number of cases being run substantially, but maintains coverage.
+ */
+export function vectorF32Range(dim) {
+ assert(dim === 2 || dim === 3 || dim === 4, 'vectorF32Range only accepts dimensions 2, 3, and 4');
+ return kVectorF32Values[dim];
+}
+
+const kSparseVectorF32Values = {
+ 2: sparseF32Range().map((f, idx) => [idx % 2 === 0 ? f : idx, idx % 2 === 1 ? f : -idx]),
+ 3: sparseF32Range().map((f, idx) => [
+ idx % 3 === 0 ? f : idx,
+ idx % 3 === 1 ? f : -idx,
+ idx % 3 === 2 ? f : idx,
+ ]),
+
+ 4: sparseF32Range().map((f, idx) => [
+ idx % 4 === 0 ? f : idx,
+ idx % 4 === 1 ? f : -idx,
+ idx % 4 === 2 ? f : idx,
+ idx % 4 === 3 ? f : -idx,
+ ]),
+};
+
+/**
+ * Minimal set of vectors, indexed by dimension, that contain interesting float
+ * values.
+ *
+ * This is an even more stripped down version of `vectorF32Range` for when
+ * pairs of vectors are being tested.
+ * All of the interesting floats from sparseF32 are guaranteed to be tested, but
+ * not in every position.
+ */
+export function sparseVectorF32Range(dim) {
+ assert(
+ dim === 2 || dim === 3 || dim === 4,
+ 'sparseVectorF32Range only accepts dimensions 2, 3, and 4'
+ );
+
+ return kSparseVectorF32Values[dim];
+}
+/**
+ * @returns the result matrix in Array<Array<number>> type.
+ *
+ * Matrix multiplication. A is m x n and B is n x p. Returns
+ * m x p result.
+ */
+// A is m x n. B is n x p. product is m x p.
+export function multiplyMatrices(A, B) {
+ assert(A.length > 0 && B.length > 0 && B[0].length > 0 && A[0].length === B.length);
+ const product = new Array(A.length);
+ for (let i = 0; i < product.length; ++i) {
+ product[i] = new Array(B[0].length).fill(0);
+ }
+
+ for (let m = 0; m < A.length; ++m) {
+ for (let p = 0; p < B[0].length; ++p) {
+ for (let n = 0; n < B.length; ++n) {
+ product[m][p] += A[m][n] * B[n][p];
+ }
+ }
+ }
+
+ return product;
+}
+
+/** Sign-extend the `bits`-bit number `n` to a 32-bit signed integer. */
+export function signExtend(n, bits) {
+ const shift = 32 - bits;
+ return (n << shift) >> shift;
+}
+
+/** @returns the closest 32-bit floating point value to the input */
+export function quantizeToF32(num) {
+ return f32(num).value;
+}
+
+/** @returns the closest 32-bit signed integer value to the input */
+export function quantizeToI32(num) {
+ return i32(num).value;
+}
+
+/** @returns the closest 32-bit signed integer value to the input */
+export function quantizeToU32(num) {
+ return u32(num).value;
+}
+
+/** @returns whether the number is an integer and a power of two */
+export function isPowerOfTwo(n) {
+ if (!Number.isInteger(n)) {
+ return false;
+ }
+ return n !== 0 && (n & (n - 1)) === 0;
+}
+
+/** @returns the Greatest Common Divisor (GCD) of the inputs */
+export function gcd(a, b) {
+ assert(Number.isInteger(a) && a > 0);
+ assert(Number.isInteger(b) && b > 0);
+
+ while (b !== 0) {
+ const bTemp = b;
+ b = a % b;
+ a = bTemp;
+ }
+
+ return a;
+}
+
+/** @returns the Least Common Multiplier (LCM) of the inputs */
+export function lcm(a, b) {
+ return (a * b) / gcd(a, b);
+}
+
+/** Converts a 32-bit hex value to a 32-bit float value */
+export function hexToF32(hex) {
+ return floatBitsToNumber(hex, kFloat32Format);
+}
+
+/** Converts a 16-bit hex value to a 16-bit float value */
+export function hexToF16(hex) {
+ return floatBitsToNumber(hex, kFloat16Format);
+}
+
+/** Converts two 32-bit hex values to a 64-bit float value */
+export function hexToF64(h32, l32) {
+ const u32Arr = new Uint32Array(2);
+ u32Arr[0] = l32;
+ u32Arr[1] = h32;
+ const f64Arr = new Float64Array(u32Arr.buffer);
+ return f64Arr[0];
+}
+
+/** @returns the cross of an array with the intermediate result of cartesianProduct
+ *
+ * @param elements array of values to cross with the intermediate result of
+ * cartesianProduct
+ * @param intermediate arrays of values representing the partial result of
+ * cartesianProduct
+ */
+function cartesianProductImpl(elements, intermediate) {
+ const result = [];
+ elements.forEach(e => {
+ if (intermediate.length > 0) {
+ intermediate.forEach(i => {
+ result.push([...i, e]);
+ });
+ } else {
+ result.push([e]);
+ }
+ });
+ return result;
+}
+
+/** @returns the cartesian product (NxMx...) of a set of arrays
+ *
+ * This is implemented by calculating the cross of a single input against an
+ * intermediate result for each input to build up the final array of arrays.
+ *
+ * There are examples of doing this more succinctly using map & reduce online,
+ * but they are a bit more opaque to read.
+ *
+ * @param inputs arrays of numbers to calculate cartesian product over
+ */
+export function cartesianProduct(...inputs) {
+ let result = [];
+ inputs.forEach(i => {
+ result = cartesianProductImpl(i, result);
+ });
+
+ return result;
+}
+
+/** @returns all of the permutations of an array
+ *
+ * Recursively calculates all of the permutations, does not cull duplicate
+ * entries.
+ *
+ * @param input the array to get permutations of
+ */
+export function calculatePermutations(input) {
+ if (input.length === 0) {
+ return [];
+ }
+
+ if (input.length === 1) {
+ return [input];
+ }
+
+ if (input.length === 2) {
+ return [input, [input[1], input[0]]];
+ }
+
+ const result = [];
+ input.forEach((head, idx) => {
+ const tail = input.slice(0, idx).concat(input.slice(idx + 1));
+ const permutations = calculatePermutations(tail);
+ permutations.forEach(p => {
+ result.push([head, ...p]);
+ });
+ });
+
+ return result;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/memory.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/memory.js
new file mode 100644
index 0000000000..6fcc2385de
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/memory.js
@@ -0,0 +1,26 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * Helper to exhaust VRAM until there is less than 64 MB of capacity. Returns
+ * an opaque closure which can be called to free the allocated resources later.
+ */ export async function exhaustVramUntilUnder64MB(device) {
+ const allocateUntilOom = async (device, size) => {
+ const buffers = [];
+ for (;;) {
+ device.pushErrorScope('out-of-memory');
+ const buffer = device.createBuffer({ size, usage: GPUBufferUsage.STORAGE });
+ if (await device.popErrorScope()) {
+ return buffers;
+ }
+ buffers.push(buffer);
+ }
+ };
+
+ const kLargeChunkSize = 512 * 1024 * 1024;
+ const kSmallChunkSize = 64 * 1024 * 1024;
+ const buffers = await allocateUntilOom(device, kLargeChunkSize);
+ buffers.push(...(await allocateUntilOom(device, kSmallChunkSize)));
+ return () => {
+ buffers.forEach(buffer => buffer.destroy());
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js
new file mode 100644
index 0000000000..41d519f6b3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/pretty_diff_tables.js
@@ -0,0 +1,49 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { range } from '../../common/util/util.js';
+/**
+ * Pretty-prints a "table" of cell values (each being `number | string`), right-aligned.
+ * Each row may be any iterator, including lazily-generated (potentially infinite) rows.
+ *
+ * The first argument is the printing options:
+ * - fillToWidth: Keep printing columns (as long as there is data) until this width is passed.
+ * If there is more data, "..." is appended.
+ * - numberToString: if a cell value is a number, this is used to stringify it.
+ *
+ * Each remaining argument provides one row for the table.
+ */
+export function generatePrettyTable({ fillToWidth, numberToString }, rows) {
+ const rowStrings = range(rows.length, () => '');
+ let totalTableWidth = 0;
+ const iters = rows.map(row => row[Symbol.iterator]());
+
+ // Loop over columns
+ for (;;) {
+ const cellsForColumn = iters.map(iter => {
+ const r = iter.next(); // Advance the iterator for each row, in lock-step.
+ return r.done ? undefined : typeof r.value === 'number' ? numberToString(r.value) : r.value;
+ });
+ if (cellsForColumn.every(cell => cell === undefined)) break;
+
+ // Maximum width of any cell in this column, plus one for space between columns
+ // (also inserts a space at the left of the first column).
+ const colWidth = Math.max(...cellsForColumn.map(c => (c === undefined ? 0 : c.length))) + 1;
+ for (let row = 0; row < rowStrings.length; ++row) {
+ const cell = cellsForColumn[row];
+ if (cell !== undefined) {
+ rowStrings[row] += cell.padStart(colWidth);
+ }
+ }
+
+ totalTableWidth += colWidth;
+ if (totalTableWidth >= fillToWidth) {
+ for (let row = 0; row < rowStrings.length; ++row) {
+ if (cellsForColumn[row] !== undefined) {
+ rowStrings[row] += ' ...';
+ }
+ }
+ break;
+ }
+ }
+ return rowStrings.join('\n');
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js
new file mode 100644
index 0000000000..2763d30a39
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/shader.js
@@ -0,0 +1,194 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { unreachable } from '../../common/util/util.js';
+export const kDefaultVertexShaderCode = `
+@vertex fn main() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+}
+`;
+
+export const kDefaultFragmentShaderCode = `
+@fragment fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(1.0, 1.0, 1.0, 1.0);
+}`;
+
+const kPlainTypeInfo = {
+ i32: {
+ suffix: '',
+ fractionDigits: 0,
+ },
+ u32: {
+ suffix: 'u',
+ fractionDigits: 0,
+ },
+ f32: {
+ suffix: '',
+ fractionDigits: 4,
+ },
+};
+
+/**
+ *
+ * @param sampleType sampleType of texture format
+ * @returns plain type compatible of the sampleType
+ */
+export function getPlainTypeInfo(sampleType) {
+ switch (sampleType) {
+ case 'sint':
+ return 'i32';
+ case 'uint':
+ return 'u32';
+ case 'float':
+ case 'unfilterable-float':
+ case 'depth':
+ return 'f32';
+ default:
+ unreachable();
+ }
+}
+
+/**
+ * Build a fragment shader based on output value and types
+ * e.g. write to color target 0 a `vec4<f32>(1.0, 0.0, 1.0, 1.0)` and color target 2 a `vec2<u32>(1, 2)`
+ * ```
+ * outputs: [
+ * {
+ * values: [1, 0, 1, 1],,
+ * plainType: 'f32',
+ * componentCount: 4,
+ * },
+ * null,
+ * {
+ * values: [1, 2],
+ * plainType: 'u32',
+ * componentCount: 2,
+ * },
+ * ]
+ * ```
+ *
+ * return:
+ * ```
+ * struct Outputs {
+ * @location(0) o1 : vec4<f32>,
+ * @location(2) o3 : vec2<u32>,
+ * }
+ * @fragment fn main() -> Outputs {
+ * return Outputs(vec4<f32>(1.0, 0.0, 1.0, 1.0), vec4<u32>(1, 2));
+ * }
+ * ```
+ *
+ * If fragDepth is given there will be an extra @builtin(frag_depth) output with the specified value assigned.
+ *
+ * @param outputs the shader outputs for each location attribute
+ * @param fragDepth the shader outputs frag_depth value (optional)
+ * @returns the fragment shader string
+ */
+export function getFragmentShaderCodeWithOutput(
+ outputs,
+
+ fragDepth = null
+) {
+ if (outputs.length === 0) {
+ if (fragDepth) {
+ return `
+ @fragment fn main() -> @builtin(frag_depth) f32 {
+ return ${fragDepth.value.toFixed(kPlainTypeInfo['f32'].fractionDigits)};
+ }`;
+ }
+ return `
+ @fragment fn main() {
+ }`;
+ }
+
+ const resultStrings = [];
+ let outputStructString = '';
+
+ if (fragDepth) {
+ resultStrings.push(`${fragDepth.value.toFixed(kPlainTypeInfo['f32'].fractionDigits)}`);
+ outputStructString += `@builtin(frag_depth) depth_out: f32,\n`;
+ }
+
+ for (let i = 0; i < outputs.length; i++) {
+ const o = outputs[i];
+ if (o === null) {
+ continue;
+ }
+
+ const plainType = o.plainType;
+ const { suffix, fractionDigits } = kPlainTypeInfo[plainType];
+
+ let outputType;
+ const v = o.values.map(n => n.toFixed(fractionDigits));
+ switch (o.componentCount) {
+ case 1:
+ outputType = plainType;
+ resultStrings.push(`${v[0]}${suffix}`);
+ break;
+ case 2:
+ outputType = `vec2<${plainType}>`;
+ resultStrings.push(`${outputType}(${v[0]}${suffix}, ${v[1]}${suffix})`);
+ break;
+ case 3:
+ outputType = `vec3<${plainType}>`;
+ resultStrings.push(`${outputType}(${v[0]}${suffix}, ${v[1]}${suffix}, ${v[2]}${suffix})`);
+ break;
+ case 4:
+ outputType = `vec4<${plainType}>`;
+ resultStrings.push(
+ `${outputType}(${v[0]}${suffix}, ${v[1]}${suffix}, ${v[2]}${suffix}, ${v[3]}${suffix})`
+ );
+
+ break;
+ default:
+ unreachable();
+ }
+
+ outputStructString += `@location(${i}) o${i} : ${outputType},\n`;
+ }
+
+ return `
+ struct Outputs {
+ ${outputStructString}
+ }
+
+ @fragment fn main() -> Outputs {
+ return Outputs(${resultStrings.join(',')});
+ }`;
+}
+
+/**
+ * Return a foo shader of the given stage with the given entry point
+ * @param shaderStage
+ * @param entryPoint
+ * @returns the shader string
+ */
+export function getShaderWithEntryPoint(shaderStage, entryPoint) {
+ let code;
+ switch (shaderStage) {
+ case 'compute': {
+ code = `@compute @workgroup_size(1) fn ${entryPoint}() {}`;
+ break;
+ }
+ case 'vertex': {
+ code = `
+ @vertex fn ${entryPoint}() -> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`;
+ break;
+ }
+ case 'fragment': {
+ code = `
+ @fragment fn ${entryPoint}() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`;
+ break;
+ }
+ case 'empty':
+ default: {
+ code = '';
+ break;
+ }
+ }
+
+ return code;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture.js
new file mode 100644
index 0000000000..70b9c8d9e9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture.js
@@ -0,0 +1,59 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../common/util/util.js';
+import { kTextureFormatInfo } from '../capability_info.js';
+import { align } from './math.js';
+
+import { reifyExtent3D } from './unions.js';
+
+/**
+ * Creates a texture with the contents of a TexelView.
+ */
+export function makeTextureWithContents(device, texelView, desc) {
+ const { width, height, depthOrArrayLayers } = reifyExtent3D(desc.size);
+
+ const { bytesPerBlock, blockWidth } = kTextureFormatInfo[texelView.format];
+ // Currently unimplemented for compressed textures.
+ assert(blockWidth === 1);
+
+ // Compute bytes per row.
+ const bytesPerRow = align(bytesPerBlock * width, 256);
+
+ // Create a staging buffer to upload the texture contents.
+ const stagingBuffer = device.createBuffer({
+ mappedAtCreation: true,
+ size: bytesPerRow * height * depthOrArrayLayers,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+
+ // Write the texels into the staging buffer.
+ texelView.writeTextureData(new Uint8Array(stagingBuffer.getMappedRange()), {
+ bytesPerRow,
+ rowsPerImage: height,
+ subrectOrigin: [0, 0, 0],
+ subrectSize: [width, height, depthOrArrayLayers],
+ });
+ stagingBuffer.unmap();
+
+ // Create the texture.
+ const texture = device.createTexture({
+ ...desc,
+ format: texelView.format,
+ usage: desc.usage | GPUTextureUsage.COPY_DST,
+ });
+
+ // Copy from the staging buffer into the texture.
+ const commandEncoder = device.createCommandEncoder();
+ commandEncoder.copyBufferToTexture(
+ { buffer: stagingBuffer, bytesPerRow },
+ { texture },
+ desc.size
+ );
+
+ device.queue.submit([commandEncoder.finish()]);
+
+ // Clean up the staging buffer.
+ stagingBuffer.destroy();
+
+ return texture;
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js
new file mode 100644
index 0000000000..cc92744b78
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/base.js
@@ -0,0 +1,199 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import { align } from '../../util/math.js';
+import { reifyExtent3D } from '../../util/unions.js';
+
+/**
+ * Compute the maximum mip level count allowed for a given texture size and texture dimension.
+ */
+export function maxMipLevelCount({ size, dimension = '2d' }) {
+ const sizeDict = reifyExtent3D(size);
+
+ let maxMippedDimension = 0;
+ switch (dimension) {
+ case '1d':
+ maxMippedDimension = 1; // No mipmaps allowed.
+ break;
+ case '2d':
+ maxMippedDimension = Math.max(sizeDict.width, sizeDict.height);
+ break;
+ case '3d':
+ maxMippedDimension = Math.max(sizeDict.width, sizeDict.height, sizeDict.depthOrArrayLayers);
+ break;
+ }
+
+ return Math.floor(Math.log2(maxMippedDimension)) + 1;
+}
+
+/**
+ * Compute the "physical size" of a mip level: the size of the level, rounded up to a
+ * multiple of the texel block size.
+ */
+export function physicalMipSize(baseSize, format, dimension, level) {
+ switch (dimension) {
+ case '1d':
+ assert(level === 0, '1d textures cannot be mipmapped');
+ assert(baseSize.height === 1 && baseSize.depthOrArrayLayers === 1, '1d texture not Wx1x1');
+ return { width: baseSize.width, height: 1, depthOrArrayLayers: 1 };
+
+ case '2d': {
+ assert(
+ Math.max(baseSize.width, baseSize.height) >> level > 0,
+ () => `level (${level}) too large for base size (${baseSize.width}x${baseSize.height})`
+ );
+
+ const virtualWidthAtLevel = Math.max(baseSize.width >> level, 1);
+ const virtualHeightAtLevel = Math.max(baseSize.height >> level, 1);
+ const physicalWidthAtLevel = align(
+ virtualWidthAtLevel,
+ kTextureFormatInfo[format].blockWidth
+ );
+
+ const physicalHeightAtLevel = align(
+ virtualHeightAtLevel,
+ kTextureFormatInfo[format].blockHeight
+ );
+
+ return {
+ width: physicalWidthAtLevel,
+ height: physicalHeightAtLevel,
+ depthOrArrayLayers: baseSize.depthOrArrayLayers,
+ };
+ }
+
+ case '3d': {
+ assert(
+ Math.max(baseSize.width, baseSize.height, baseSize.depthOrArrayLayers) >> level > 0,
+ () =>
+ `level (${level}) too large for base size (${baseSize.width}x${baseSize.height}x${baseSize.depthOrArrayLayers})`
+ );
+
+ assert(
+ kTextureFormatInfo[format].blockWidth === 1 && kTextureFormatInfo[format].blockHeight === 1,
+ 'not implemented for 3d block formats'
+ );
+
+ return {
+ width: Math.max(baseSize.width >> level, 1),
+ height: Math.max(baseSize.height >> level, 1),
+ depthOrArrayLayers: Math.max(baseSize.depthOrArrayLayers >> level, 1),
+ };
+ }
+ }
+}
+
+/**
+ * Compute the "virtual size" of a mip level of a texture (not accounting for texel block rounding).
+ *
+ * MAINTENANCE_TODO: Change input/output to Required<GPUExtent3DDict> for consistency.
+ */
+export function virtualMipSize(dimension, size, mipLevel) {
+ const shiftMinOne = n => Math.max(1, n >> mipLevel);
+ switch (dimension) {
+ case '1d':
+ assert(size[2] === 1);
+ return [shiftMinOne(size[0]), size[1], size[2]];
+ case '2d':
+ return [shiftMinOne(size[0]), shiftMinOne(size[1]), size[2]];
+ case '3d':
+ return [shiftMinOne(size[0]), shiftMinOne(size[1]), shiftMinOne(size[2])];
+ default:
+ unreachable();
+ }
+}
+
+/**
+ * Get texture dimension from view dimension in order to create an compatible texture for a given
+ * view dimension.
+ */
+export function getTextureDimensionFromView(viewDimension) {
+ switch (viewDimension) {
+ case '1d':
+ return '1d';
+ case '2d':
+ case '2d-array':
+ case 'cube':
+ case 'cube-array':
+ return '2d';
+ case '3d':
+ return '3d';
+ default:
+ unreachable();
+ }
+}
+
+/** Returns the possible valid view dimensions for a given texture dimension. */
+export function viewDimensionsForTextureDimension(textureDimension) {
+ switch (textureDimension) {
+ case '1d':
+ return ['1d'];
+ case '2d':
+ return ['2d', '2d-array', 'cube', 'cube-array'];
+ case '3d':
+ return ['3d'];
+ }
+}
+
+/** Returns the default view dimension for a given texture descriptor. */
+export function defaultViewDimensionsForTexture(textureDescriptor) {
+ switch (textureDescriptor.dimension) {
+ case '1d':
+ return '1d';
+ case '2d': {
+ const sizeDict = reifyExtent3D(textureDescriptor.size);
+ return sizeDict.depthOrArrayLayers > 1 ? '2d-array' : '2d';
+ }
+ case '3d':
+ return '3d';
+ default:
+ unreachable();
+ }
+}
+
+/** Reifies the optional fields of `GPUTextureDescriptor`.
+ * MAINTENANCE_TODO: viewFormats should not be omitted here, but it seems likely that the
+ * @webgpu/types definition will have to change before we can include it again.
+ */
+export function reifyTextureDescriptor(desc) {
+ return { dimension: '2d', mipLevelCount: 1, sampleCount: 1, ...desc };
+}
+
+/** Reifies the optional fields of `GPUTextureViewDescriptor` (given a `GPUTextureDescriptor`). */
+export function reifyTextureViewDescriptor(textureDescriptor, view) {
+ const texture = reifyTextureDescriptor(textureDescriptor);
+
+ // IDL defaulting
+
+ const baseMipLevel = view.baseMipLevel ?? 0;
+ const baseArrayLayer = view.baseArrayLayer ?? 0;
+ const aspect = view.aspect ?? 'all';
+
+ // Spec defaulting
+
+ const format = view.format ?? texture.format;
+ const mipLevelCount = view.mipLevelCount ?? texture.mipLevelCount - baseMipLevel;
+ const dimension = view.dimension ?? defaultViewDimensionsForTexture(texture);
+
+ let arrayLayerCount = view.arrayLayerCount;
+ if (arrayLayerCount === undefined) {
+ if (dimension === '2d-array' || dimension === 'cube-array') {
+ arrayLayerCount = reifyExtent3D(texture.size).depthOrArrayLayers - baseArrayLayer;
+ } else if (dimension === 'cube') {
+ arrayLayerCount = 6;
+ } else {
+ arrayLayerCount = 1;
+ }
+ }
+
+ return {
+ format,
+ dimension,
+ aspect,
+ baseMipLevel,
+ mipLevelCount,
+ baseArrayLayer,
+ arrayLayerCount,
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/data_generation.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/data_generation.js
new file mode 100644
index 0000000000..b92dbd2bbd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/data_generation.js
@@ -0,0 +1,84 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * A helper class that generates ranges of dummy data for buffer or texture operations
+ * efficiently. Tries to minimize allocations and data updates.
+ */ export class DataArrayGenerator {
+ dataBuffer = new Uint8Array(256);
+
+ lastOffset = 0;
+ lastStart = 0;
+ lastByteSize = 0;
+
+ /** Find the nearest power of two greater than or equal to the input value. */
+ nextPowerOfTwo(value) {
+ return 1 << (32 - Math.clz32(value - 1));
+ }
+
+ generateData(byteSize, start = 0, offset = 0) {
+ const prevSize = this.dataBuffer.length;
+
+ if (prevSize < byteSize) {
+ // If the requested data is larger than the allocated buffer, reallocate it to a buffer large
+ // enough to handle the new request.
+ const newData = new Uint8Array(this.nextPowerOfTwo(byteSize));
+
+ if (this.lastOffset === offset && this.lastStart === start && this.lastByteSize) {
+ // Do a fast copy of any previous data that was generated.
+ newData.set(this.dataBuffer);
+ }
+
+ this.dataBuffer = newData;
+ } else if (this.lastOffset < offset) {
+ // Ensure all values up to the offset are zeroed out.
+ this.dataBuffer.fill(0, this.lastOffset, offset);
+ }
+
+ // If the offset or start values have changed, the whole data range needs to be regenerated.
+ if (this.lastOffset !== offset || this.lastStart !== start) {
+ this.lastByteSize = 0;
+ }
+
+ // Generate any new values that are required
+ if (this.lastByteSize < byteSize) {
+ for (let i = this.lastByteSize; i < byteSize - offset; ++i) {
+ this.dataBuffer[i + offset] = ((i ** 3 + i + start) % 251) + 1; // Ensure data is always non-zero
+ }
+
+ this.lastOffset = offset;
+ this.lastStart = start;
+ this.lastByteSize = byteSize;
+ }
+ }
+
+ /**
+ * Returns a new view into the generated data that's the correct length. Because this is a view
+ * previously returned views from the same generator will have their values overwritten as well.
+ * @param {number} byteSize - Number of bytes the returned view should contain.
+ * @param {number} [start] - The value of the first element generated in the view.
+ * @param {number} [offset] - Offset of the generated data within the view. Preceeding values will be 0.
+ * @returns {Uint8Array} A new Uint8Array view into the generated data.
+ */
+ generateView(byteSize, start = 0, offset = 0) {
+ this.generateData(byteSize, start, offset);
+
+ if (this.dataBuffer.length === byteSize) {
+ return this.dataBuffer;
+ }
+ return new Uint8Array(this.dataBuffer.buffer, 0, byteSize);
+ }
+
+ /**
+ * Returns a copy of the generated data. Note that this still changes the underlying buffer, so
+ * any previously generated views will still be overwritten, but the returned copy won't reflect
+ * future generate* calls.
+ * @param {number} byteSize - Number of bytes the returned array should contain.
+ * @param {number} [start] - The value of the first element generated in the view.
+ * @param {number} [offset] - Offset of the generated data within the view. Preceeding values will be 0.
+ * @returns {Uint8Array} A new Uint8Array copy of the generated data.
+ */
+ generateAndCopyView(byteSize, start = 0, offset = 0) {
+ this.generateData(byteSize, start, offset);
+ return this.dataBuffer.slice(0, byteSize);
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/layout.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/layout.js
new file mode 100644
index 0000000000..bd3cbbd99f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/layout.js
@@ -0,0 +1,302 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, memcpy } from '../../../common/util/util.js';
+import { kTextureFormatInfo, resolvePerAspectFormat } from '../../capability_info.js';
+import { align } from '../math.js';
+import { reifyExtent3D } from '../unions.js';
+
+import { physicalMipSize, virtualMipSize } from './base.js';
+
+/** The minimum `bytesPerRow` alignment, per spec. */
+export const kBytesPerRowAlignment = 256;
+/** The minimum buffer copy alignment, per spec. */
+export const kBufferCopyAlignment = 4;
+
+/**
+ * Overridable layout options for {@link getTextureCopyLayout}.
+ */
+
+const kDefaultLayoutOptions = {
+ mipLevel: 0,
+ bytesPerRow: undefined,
+ rowsPerImage: undefined,
+ aspect: 'all',
+};
+
+/** The info returned by {@link getTextureSubCopyLayout}. */
+
+/**
+ * Computes layout information for a copy of the whole subresource at `mipLevel` of a GPUTexture
+ * of size `baseSize` with the provided `format` and `dimension`.
+ *
+ * Computes default values for `bytesPerRow` and `rowsPerImage` if not specified.
+ *
+ * MAINTENANCE_TODO: Change input/output to Required<GPUExtent3DDict> for consistency.
+ */
+export function getTextureCopyLayout(
+ format,
+ dimension,
+ baseSize,
+ { mipLevel, bytesPerRow, rowsPerImage, aspect } = kDefaultLayoutOptions
+) {
+ const mipSize = physicalMipSize(
+ { width: baseSize[0], height: baseSize[1], depthOrArrayLayers: baseSize[2] },
+ format,
+ dimension,
+ mipLevel
+ );
+
+ const layout = getTextureSubCopyLayout(format, mipSize, { bytesPerRow, rowsPerImage, aspect });
+ return { ...layout, mipSize: [mipSize.width, mipSize.height, mipSize.depthOrArrayLayers] };
+}
+
+/**
+ * Computes layout information for a copy of size `copySize` to/from a GPUTexture with the provided
+ * `format`.
+ *
+ * Computes default values for `bytesPerRow` and `rowsPerImage` if not specified.
+ */
+export function getTextureSubCopyLayout(
+ format,
+ copySize,
+ { bytesPerRow, rowsPerImage, aspect = 'all' } = {}
+) {
+ format = resolvePerAspectFormat(format, aspect);
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ assert(bytesPerBlock !== undefined);
+
+ const copySize_ = reifyExtent3D(copySize);
+ assert(
+ copySize_.width > 0 && copySize_.height > 0 && copySize_.depthOrArrayLayers > 0,
+ 'not implemented for empty copySize'
+ );
+
+ assert(
+ copySize_.width % blockWidth === 0 && copySize_.height % blockHeight === 0,
+ 'copySize must be a multiple of the block size'
+ );
+
+ const copySizeBlocks = {
+ width: copySize_.width / blockWidth,
+ height: copySize_.height / blockHeight,
+ depthOrArrayLayers: copySize_.depthOrArrayLayers,
+ };
+
+ const minBytesPerRow = copySizeBlocks.width * bytesPerBlock;
+ const alignedMinBytesPerRow = align(minBytesPerRow, kBytesPerRowAlignment);
+ if (bytesPerRow !== undefined) {
+ assert(bytesPerRow >= alignedMinBytesPerRow);
+ assert(bytesPerRow % kBytesPerRowAlignment === 0);
+ } else {
+ bytesPerRow = alignedMinBytesPerRow;
+ }
+
+ if (rowsPerImage !== undefined) {
+ assert(rowsPerImage >= copySizeBlocks.height);
+ } else {
+ rowsPerImage = copySizeBlocks.height;
+ }
+
+ const bytesPerSlice = bytesPerRow * rowsPerImage;
+ const sliceSize =
+ bytesPerRow * (copySizeBlocks.height - 1) + bytesPerBlock * copySizeBlocks.width;
+ const byteLength = bytesPerSlice * (copySizeBlocks.depthOrArrayLayers - 1) + sliceSize;
+
+ return {
+ bytesPerBlock,
+ byteLength: align(byteLength, kBufferCopyAlignment),
+ minBytesPerRow,
+ bytesPerRow,
+ rowsPerImage,
+ };
+}
+
+/**
+ * Fill an ArrayBuffer with the linear-memory representation of a solid-color
+ * texture where every texel has the byte value `texelValue`.
+ * Preserves the contents of `outputBuffer` which are in "padding" space between image rows.
+ *
+ * Effectively emulates a copyTextureToBuffer from a solid-color texture to a buffer.
+ */
+export function fillTextureDataWithTexelValue(
+ texelValue,
+ format,
+ dimension,
+ outputBuffer,
+ size,
+ options = kDefaultLayoutOptions
+) {
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ // Block formats are not handled correctly below.
+ assert(blockWidth === 1);
+ assert(blockHeight === 1);
+
+ assert(bytesPerBlock === texelValue.byteLength, 'texelValue must be of size bytesPerBlock');
+
+ const { byteLength, rowsPerImage, bytesPerRow } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ options
+ );
+
+ assert(byteLength <= outputBuffer.byteLength);
+
+ const mipSize = virtualMipSize(dimension, size, options.mipLevel);
+
+ const outputTexelValueBytes = new Uint8Array(outputBuffer);
+ for (let slice = 0; slice < mipSize[2]; ++slice) {
+ for (let row = 0; row < mipSize[1]; row += blockHeight) {
+ for (let col = 0; col < mipSize[0]; col += blockWidth) {
+ const byteOffset =
+ slice * rowsPerImage * bytesPerRow + row * bytesPerRow + col * texelValue.byteLength;
+ memcpy({ src: texelValue }, { dst: outputTexelValueBytes, start: byteOffset });
+ }
+ }
+ }
+}
+
+/**
+ * Create a `COPY_SRC` GPUBuffer containing the linear-memory representation of a solid-color
+ * texture where every texel has the byte value `texelValue`.
+ */
+export function createTextureUploadBuffer(
+ texelValue,
+ device,
+ format,
+ dimension,
+ size,
+ options = kDefaultLayoutOptions
+) {
+ const { byteLength, bytesPerRow, rowsPerImage, bytesPerBlock } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ options
+ );
+
+ const buffer = device.createBuffer({
+ mappedAtCreation: true,
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ const mapping = buffer.getMappedRange();
+
+ assert(texelValue.byteLength === bytesPerBlock);
+ fillTextureDataWithTexelValue(texelValue, format, dimension, mapping, size, options);
+ buffer.unmap();
+
+ return {
+ buffer,
+ bytesPerRow,
+ rowsPerImage,
+ };
+}
+
+export const kImageCopyTypes = ['WriteTexture', 'CopyB2T', 'CopyT2B'];
+
+/**
+ * Computes `bytesInACompleteRow` (as defined by the WebGPU spec) for image copies (B2T/T2B/writeTexture).
+ */
+export function bytesInACompleteRow(copyWidth, format) {
+ const info = kTextureFormatInfo[format];
+ assert(copyWidth % info.blockWidth === 0);
+ return (info.bytesPerBlock * copyWidth) / info.blockWidth;
+}
+
+function validateBytesPerRow({ bytesPerRow, bytesInLastRow, sizeInBlocks }) {
+ // If specified, layout.bytesPerRow must be greater than or equal to bytesInLastRow.
+ if (bytesPerRow !== undefined && bytesPerRow < bytesInLastRow) {
+ return false;
+ }
+ // If heightInBlocks > 1, layout.bytesPerRow must be specified.
+ // If copyExtent.depthOrArrayLayers > 1, layout.bytesPerRow and layout.rowsPerImage must be specified.
+ if (
+ bytesPerRow === undefined &&
+ (sizeInBlocks.height > 1 || sizeInBlocks.depthOrArrayLayers > 1)
+ ) {
+ return false;
+ }
+ return true;
+}
+
+function validateRowsPerImage({ rowsPerImage, sizeInBlocks }) {
+ // If specified, layout.rowsPerImage must be greater than or equal to heightInBlocks.
+ if (rowsPerImage !== undefined && rowsPerImage < sizeInBlocks.height) {
+ return false;
+ }
+ // If copyExtent.depthOrArrayLayers > 1, layout.bytesPerRow and layout.rowsPerImage must be specified.
+ if (rowsPerImage === undefined && sizeInBlocks.depthOrArrayLayers > 1) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Validate a copy and compute the number of bytes it needs. Throws if the copy is invalid.
+ */
+export function dataBytesForCopyOrFail(args) {
+ const { minDataSizeOrOverestimate, copyValid } = dataBytesForCopyOrOverestimate(args);
+ assert(copyValid, 'copy was invalid');
+ return minDataSizeOrOverestimate;
+}
+
+/**
+ * Validate a copy and compute the number of bytes it needs. If the copy is invalid, attempts to
+ * "conservatively guess" (overestimate) the number of bytes that could be needed for a copy, even
+ * if the copy parameters turn out to be invalid. This hopes to avoid "buffer too small" validation
+ * errors when attempting to test other validation errors.
+ */
+export function dataBytesForCopyOrOverestimate({ layout, format, copySize: copySize_, method }) {
+ const copyExtent = reifyExtent3D(copySize_);
+
+ const info = kTextureFormatInfo[format];
+ assert(copyExtent.width % info.blockWidth === 0);
+ assert(copyExtent.height % info.blockHeight === 0);
+ const sizeInBlocks = {
+ width: copyExtent.width / info.blockWidth,
+ height: copyExtent.height / info.blockHeight,
+ depthOrArrayLayers: copyExtent.depthOrArrayLayers,
+ };
+ const bytesInLastRow = sizeInBlocks.width * info.bytesPerBlock;
+
+ let valid = true;
+ const offset = layout.offset ?? 0;
+ if (method !== 'WriteTexture') {
+ if (offset % info.bytesPerBlock !== 0) valid = false;
+ if (layout.bytesPerRow && layout.bytesPerRow % 256 !== 0) valid = false;
+ }
+
+ let requiredBytesInCopy = 0;
+ {
+ let { bytesPerRow, rowsPerImage } = layout;
+
+ // If bytesPerRow or rowsPerImage is invalid, guess a value for the sake of various tests that
+ // don't actually care about the exact value.
+ // (In particular for validation tests that want to test invalid bytesPerRow or rowsPerImage but
+ // need to make sure the total buffer size is still big enough.)
+ if (!validateBytesPerRow({ bytesPerRow, bytesInLastRow, sizeInBlocks })) {
+ bytesPerRow = undefined;
+ valid = false;
+ }
+ if (!validateRowsPerImage({ rowsPerImage, sizeInBlocks })) {
+ rowsPerImage = undefined;
+ valid = false;
+ }
+ // Pick values for cases when (a) bpr/rpi was invalid or (b) they're validly undefined.
+ bytesPerRow ??= align(info.bytesPerBlock * sizeInBlocks.width, 256);
+ rowsPerImage ??= sizeInBlocks.height;
+
+ if (copyExtent.depthOrArrayLayers > 1) {
+ const bytesPerImage = bytesPerRow * rowsPerImage;
+ const bytesBeforeLastImage = bytesPerImage * (copyExtent.depthOrArrayLayers - 1);
+ requiredBytesInCopy += bytesBeforeLastImage;
+ }
+ if (copyExtent.depthOrArrayLayers > 0) {
+ if (sizeInBlocks.height > 1) requiredBytesInCopy += bytesPerRow * (sizeInBlocks.height - 1);
+ if (sizeInBlocks.height > 0) requiredBytesInCopy += bytesInLastRow;
+ }
+ }
+
+ return { minDataSizeOrOverestimate: offset + requiredBytesInCopy, copyValid: valid };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/subresource.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/subresource.js
new file mode 100644
index 0000000000..db9f637d44
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/subresource.js
@@ -0,0 +1,54 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+
+function endOfRange(r) {
+ return 'count' in r ? r.begin + r.count : r.end;
+}
+
+function* rangeAsIterator(r) {
+ for (let i = r.begin; i < endOfRange(r); ++i) {
+ yield i;
+ }
+}
+
+/**
+ * Represents a range of subresources of a single-plane texture:
+ * a min/max mip level and min/max array layer.
+ */
+export class SubresourceRange {
+ constructor(subresources) {
+ this.mipRange = {
+ begin: subresources.mipRange.begin,
+ end: endOfRange(subresources.mipRange),
+ };
+ this.layerRange = {
+ begin: subresources.layerRange.begin,
+ end: endOfRange(subresources.layerRange),
+ };
+ }
+
+ /**
+ * Iterates over the "rectangle" of `{ level, layer }` pairs represented by the range.
+ */
+ *each() {
+ for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) {
+ for (let layer = this.layerRange.begin; layer < this.layerRange.end; ++layer) {
+ yield { level, layer };
+ }
+ }
+ }
+
+ /**
+ * Iterates over the mip levels represented by the range, each level including an iterator
+ * over the array layers at that level.
+ */
+ *mipLevels() {
+ for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) {
+ yield {
+ level,
+ layers: rangeAsIterator(this.layerRange),
+ };
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js
new file mode 100644
index 0000000000..e98fb72c14
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.js
@@ -0,0 +1,852 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../common/util/util.js';
+import {
+ assertInIntegerRange,
+ float32ToFloatBits,
+ float32ToFloat16Bits,
+ floatAsNormalizedInteger,
+ gammaCompress,
+ gammaDecompress,
+ normalizedIntegerAsFloat,
+ packRGB9E5UFloat,
+ floatBitsToNumber,
+ float16BitsToFloat32,
+ floatBitsToNormalULPFromZero,
+ kFloat32Format,
+ kFloat16Format,
+ numberToFloat32Bits,
+ float32BitsToNumber,
+ numberToFloatBits,
+} from '../conversion.js';
+import { clamp, signExtend } from '../math.js';
+
+/** A component of a texture format: R, G, B, A, Depth, or Stencil. */
+export let TexelComponent;
+
+/** Arbitrary data, per component of a texel format. */ (function (TexelComponent) {
+ TexelComponent['R'] = 'R';
+ TexelComponent['G'] = 'G';
+ TexelComponent['B'] = 'B';
+ TexelComponent['A'] = 'A';
+ TexelComponent['Depth'] = 'Depth';
+ TexelComponent['Stencil'] = 'Stencil';
+})(TexelComponent || (TexelComponent = {}));
+
+/**
+ * Create a PerTexelComponent object filled with the same value for all components.
+ * @param {TexelComponent[]} components - The component names.
+ * @param {T} value - The value to assign to each component.
+ * @returns {PerTexelComponent<T>}
+ */
+function makePerTexelComponent(components, value) {
+ const values = {};
+ for (const c of components) {
+ values[c] = value;
+ }
+ return values;
+}
+
+/**
+ * Create a function which applies clones a `PerTexelComponent<number>` and then applies the
+ * function `fn` to each component of `components`.
+ * @param {(value: number) => number} fn - The mapping function to apply to component values.
+ * @param {TexelComponent[]} components - The component names.
+ * @returns {ComponentMapFn} The map function which clones the input component values, and applies
+ * `fn` to each of component of `components`.
+ */
+function applyEach(fn, components) {
+ return values => {
+ values = Object.assign({}, values);
+ for (const c of components) {
+ assert(values[c] !== undefined);
+ values[c] = fn(values[c]);
+ }
+ return values;
+ };
+}
+
+/**
+ * A `ComponentMapFn` for encoding sRGB.
+ * @param {PerTexelComponent<number>} components - The input component values.
+ * @returns {TexelComponent<number>} Gamma-compressed copy of `components`.
+ */
+const encodeSRGB = components => {
+ assert(
+ components.R !== undefined && components.G !== undefined && components.B !== undefined,
+ 'sRGB requires all of R, G, and B components'
+ );
+
+ return applyEach(gammaCompress, kRGB)(components);
+};
+
+/**
+ * A `ComponentMapFn` for decoding sRGB.
+ * @param {PerTexelComponent<number>} components - The input component values.
+ * @returns {TexelComponent<number>} Gamma-decompressed copy of `components`.
+ */
+const decodeSRGB = components => {
+ components = Object.assign({}, components);
+ assert(
+ components.R !== undefined && components.G !== undefined && components.B !== undefined,
+ 'sRGB requires all of R, G, and B components'
+ );
+
+ return applyEach(gammaDecompress, kRGB)(components);
+};
+
+/**
+ * Makes a `ComponentMapFn` for clamping values to the specified range.
+ */
+export function makeClampToRange(format) {
+ const repr = kTexelRepresentationInfo[format];
+ assert(repr.numericRange !== null, 'Format has unknown numericRange');
+ return applyEach(x => clamp(x, repr.numericRange), repr.componentOrder);
+}
+
+// MAINTENANCE_TODO: Look into exposing this map to the test fixture so that it can be GCed at the
+// end of each test group. That would allow for caching of larger buffers (though it's unclear how
+// ofter larger buffers are used by packComponents.)
+const smallComponentDataViews = new Map();
+function getComponentDataView(byteLength) {
+ if (byteLength > 32) {
+ const buffer = new ArrayBuffer(byteLength);
+ return new DataView(buffer);
+ }
+ let dataView = smallComponentDataViews.get(byteLength);
+ if (!dataView) {
+ const buffer = new ArrayBuffer(byteLength);
+ dataView = new DataView(buffer);
+ smallComponentDataViews.set(byteLength, dataView);
+ }
+ return dataView;
+}
+
+/**
+ * Helper function to pack components as an ArrayBuffer.
+ * @param {TexelComponent[]} componentOrder - The order of the component data.
+ * @param {PerTexelComponent<number>} components - The input component values.
+ * @param {number | PerTexelComponent<number>} bitLengths - The length in bits of each component.
+ * If a single number, all components are the same length, otherwise this is a dictionary of
+ * per-component bit lengths.
+ * @param {ComponentDataType | PerTexelComponent<ComponentDataType>} componentDataTypes -
+ * The type of the data in `components`. If a single value, all components have the same value.
+ * Otherwise, this is a dictionary of per-component data types.
+ * @returns {ArrayBuffer} The packed component data.
+ */
+function packComponents(componentOrder, components, bitLengths, componentDataTypes) {
+ let bitLengthMap;
+ let totalBitLength;
+ if (typeof bitLengths === 'number') {
+ bitLengthMap = makePerTexelComponent(componentOrder, bitLengths);
+ totalBitLength = bitLengths * componentOrder.length;
+ } else {
+ bitLengthMap = bitLengths;
+ totalBitLength = Object.entries(bitLengthMap).reduce((acc, [, value]) => {
+ assert(value !== undefined);
+ return acc + value;
+ }, 0);
+ }
+ assert(totalBitLength % 8 === 0);
+
+ const componentDataTypeMap =
+ typeof componentDataTypes === 'string' || componentDataTypes === null
+ ? makePerTexelComponent(componentOrder, componentDataTypes)
+ : componentDataTypes;
+
+ const dataView = getComponentDataView(totalBitLength / 8);
+ let bitOffset = 0;
+ for (const c of componentOrder) {
+ const value = components[c];
+ const type = componentDataTypeMap[c];
+ const bitLength = bitLengthMap[c];
+ assert(value !== undefined);
+ assert(type !== undefined);
+ assert(bitLength !== undefined);
+
+ const byteOffset = Math.floor(bitOffset / 8);
+ const byteLength = Math.ceil(bitLength / 8);
+ switch (type) {
+ case 'uint':
+ case 'unorm':
+ if (byteOffset === bitOffset / 8 && byteLength === bitLength / 8) {
+ switch (byteLength) {
+ case 1:
+ dataView.setUint8(byteOffset, value);
+ break;
+ case 2:
+ dataView.setUint16(byteOffset, value, true);
+ break;
+ case 4:
+ dataView.setUint32(byteOffset, value, true);
+ break;
+ default:
+ unreachable();
+ }
+ } else {
+ // Packed representations are all 32-bit and use Uint as the data type.
+ // ex.) rg10b11float, rgb10a2unorm
+ switch (dataView.byteLength) {
+ case 4: {
+ const currentValue = dataView.getUint32(0, true);
+
+ let mask = 0xffffffff;
+ const bitsToClearRight = bitOffset;
+ const bitsToClearLeft = 32 - (bitLength + bitOffset);
+
+ mask = (mask >>> bitsToClearRight) << bitsToClearRight;
+ mask = (mask << bitsToClearLeft) >>> bitsToClearLeft;
+
+ const newValue = (currentValue & ~mask) | (value << bitOffset);
+
+ dataView.setUint32(0, newValue, true);
+ break;
+ }
+ default:
+ unreachable();
+ }
+ }
+ break;
+ case 'sint':
+ case 'snorm':
+ assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8);
+ switch (byteLength) {
+ case 1:
+ dataView.setInt8(byteOffset, value);
+ break;
+ case 2:
+ dataView.setInt16(byteOffset, value, true);
+ break;
+ case 4:
+ dataView.setInt32(byteOffset, value, true);
+ break;
+ default:
+ unreachable();
+ }
+
+ break;
+ case 'float':
+ assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8);
+ switch (byteLength) {
+ case 4:
+ dataView.setFloat32(byteOffset, value, true);
+ break;
+ default:
+ unreachable();
+ }
+
+ break;
+ case 'ufloat':
+ case null:
+ unreachable();
+ }
+
+ bitOffset += bitLength;
+ }
+
+ return dataView.buffer;
+}
+
+/**
+ * Unpack substrings of bits from a Uint8Array, e.g. [8,8,8,8] or [9,9,9,5].
+ */
+function unpackComponentsBits(componentOrder, byteView, bitLengths) {
+ const components = makePerTexelComponent(componentOrder, 0);
+
+ let bitLengthMap;
+ let totalBitLength;
+ if (typeof bitLengths === 'number') {
+ let index = 0;
+ // Optimized cases for when the bit lengths are all a well aligned value.
+ switch (bitLengths) {
+ case 8:
+ for (const c of componentOrder) {
+ components[c] = byteView[index++];
+ }
+ return components;
+ case 16: {
+ const shortView = new Uint16Array(byteView.buffer, byteView.byteOffset);
+ for (const c of componentOrder) {
+ components[c] = shortView[index++];
+ }
+ return components;
+ }
+ case 32: {
+ const longView = new Uint32Array(byteView.buffer, byteView.byteOffset);
+ for (const c of componentOrder) {
+ components[c] = longView[index++];
+ }
+ return components;
+ }
+ }
+
+ bitLengthMap = makePerTexelComponent(componentOrder, bitLengths);
+ totalBitLength = bitLengths * componentOrder.length;
+ } else {
+ bitLengthMap = bitLengths;
+ totalBitLength = Object.entries(bitLengthMap).reduce((acc, [, value]) => {
+ assert(value !== undefined);
+ return acc + value;
+ }, 0);
+ }
+
+ assert(totalBitLength % 8 === 0);
+
+ const dataView = new DataView(byteView.buffer, byteView.byteOffset, byteView.byteLength);
+ let bitOffset = 0;
+ for (const c of componentOrder) {
+ const bitLength = bitLengthMap[c];
+ assert(bitLength !== undefined);
+
+ let value;
+
+ const byteOffset = Math.floor(bitOffset / 8);
+ const byteLength = Math.ceil(bitLength / 8);
+ if (byteOffset === bitOffset / 8 && byteLength === bitLength / 8) {
+ switch (byteLength) {
+ case 1:
+ value = dataView.getUint8(byteOffset);
+ break;
+ case 2:
+ value = dataView.getUint16(byteOffset, true);
+ break;
+ case 4:
+ value = dataView.getUint32(byteOffset, true);
+ break;
+ default:
+ unreachable();
+ }
+ } else {
+ // Packed representations are all 32-bit and use Uint as the data type.
+ // ex.) rg10b11float, rgb10a2unorm
+ assert(dataView.byteLength === 4);
+ const word = dataView.getUint32(0, true);
+ value = (word >>> bitOffset) & ((1 << bitLength) - 1);
+ }
+
+ bitOffset += bitLength;
+ components[c] = value;
+ }
+
+ return components;
+}
+
+/**
+ * Create an entry in `kTexelRepresentationInfo` for normalized integer texel data with constant
+ * bitlength.
+ * @param {TexelComponent[]} componentOrder - The order of the component data.
+ * @param {number} bitLength - The number of bits in each component.
+ * @param {{signed: boolean; sRGB: boolean}} opt - Boolean flags for `signed` and `sRGB`.
+ */
+function makeNormalizedInfo(componentOrder, bitLength, opt) {
+ const encodeNonSRGB = applyEach(
+ n => floatAsNormalizedInteger(n, bitLength, opt.signed),
+ componentOrder
+ );
+
+ const decodeNonSRGB = applyEach(
+ n => normalizedIntegerAsFloat(n, bitLength, opt.signed),
+ componentOrder
+ );
+
+ const numberToBitsNonSRGB = applyEach(
+ n => floatAsNormalizedInteger(n, bitLength, opt.signed),
+ componentOrder
+ );
+
+ let bitsToNumberNonSRGB;
+ if (opt.signed) {
+ bitsToNumberNonSRGB = applyEach(
+ n => normalizedIntegerAsFloat(signExtend(n, bitLength), bitLength, opt.signed),
+ componentOrder
+ );
+ } else {
+ bitsToNumberNonSRGB = applyEach(
+ n => normalizedIntegerAsFloat(n, bitLength, opt.signed),
+ componentOrder
+ );
+ }
+
+ let encode;
+ let decode;
+ let numberToBits;
+ let bitsToNumber;
+ if (opt.sRGB) {
+ encode = components => encodeNonSRGB(encodeSRGB(components));
+ decode = components => decodeSRGB(decodeNonSRGB(components));
+ numberToBits = components => numberToBitsNonSRGB(encodeSRGB(components));
+ bitsToNumber = components => decodeSRGB(bitsToNumberNonSRGB(components));
+ } else {
+ encode = encodeNonSRGB;
+ decode = decodeNonSRGB;
+ numberToBits = numberToBitsNonSRGB;
+ bitsToNumber = bitsToNumberNonSRGB;
+ }
+
+ let bitsToULPFromZero;
+ if (opt.signed) {
+ const maxValue = (1 << (bitLength - 1)) - 1; // e.g. 127 for snorm8
+ bitsToULPFromZero = applyEach(
+ n => Math.max(-maxValue, signExtend(n, bitLength)),
+ componentOrder
+ );
+ } else {
+ bitsToULPFromZero = components => components;
+ }
+
+ const dataType = opt.signed ? 'snorm' : 'unorm';
+ return {
+ componentOrder,
+ componentInfo: makePerTexelComponent(componentOrder, {
+ dataType,
+ bitLength,
+ }),
+ encode,
+ decode,
+ pack: components => packComponents(componentOrder, components, bitLength, dataType),
+ unpackBits: data => unpackComponentsBits(componentOrder, data, bitLength),
+ numberToBits,
+ bitsToNumber,
+ bitsToULPFromZero,
+ numericRange: { min: opt.signed ? -1 : 0, max: 1 },
+ };
+}
+
+/**
+ * Create an entry in `kTexelRepresentationInfo` for integer texel data with constant bitlength.
+ * @param {TexelComponent[]} componentOrder - The order of the component data.
+ * @param {number} bitLength - The number of bits in each component.
+ * @param {{signed: boolean}} opt - Boolean flag for `signed`.
+ */
+function makeIntegerInfo(componentOrder, bitLength, opt) {
+ assert(bitLength <= 32);
+ const encode = applyEach(
+ n => (assertInIntegerRange(n, bitLength, opt.signed), n),
+ componentOrder
+ );
+
+ const decode = applyEach(
+ n => (assertInIntegerRange(n, bitLength, opt.signed), n),
+ componentOrder
+ );
+
+ let bitsToULPFromZero;
+ if (opt.signed) {
+ bitsToULPFromZero = applyEach(n => signExtend(n, bitLength), componentOrder);
+ } else {
+ bitsToULPFromZero = components => components;
+ }
+
+ const dataType = opt.signed ? 'sint' : 'uint';
+ const bitMask = (1 << bitLength) - 1;
+ return {
+ componentOrder,
+ componentInfo: makePerTexelComponent(componentOrder, {
+ dataType,
+ bitLength,
+ }),
+ encode,
+ decode,
+ pack: components => packComponents(componentOrder, components, bitLength, dataType),
+ unpackBits: data => unpackComponentsBits(componentOrder, data, bitLength),
+ numberToBits: applyEach(v => v & bitMask, componentOrder),
+ bitsToNumber: decode,
+ bitsToULPFromZero,
+ numericRange: opt.signed
+ ? { min: -(2 ** (bitLength - 1)), max: 2 ** (bitLength - 1) - 1 }
+ : { min: 0, max: 2 ** bitLength - 1 },
+ };
+}
+
+/**
+ * Create an entry in `kTexelRepresentationInfo` for floating point texel data with constant
+ * bitlength.
+ * @param {TexelComponent[]} componentOrder - The order of the component data.
+ * @param {number} bitLength - The number of bits in each component.
+ */
+function makeFloatInfo(componentOrder, bitLength, { restrictedDepth = false } = {}) {
+ let encode;
+ let numberToBits;
+ let bitsToNumber;
+ let bitsToULPFromZero;
+ switch (bitLength) {
+ case 32:
+ if (restrictedDepth) {
+ encode = applyEach(v => {
+ assert(v >= 0.0 && v <= 1.0, 'depth out of range');
+ return new Float32Array([v])[0];
+ }, componentOrder);
+ } else {
+ encode = applyEach(v => new Float32Array([v])[0], componentOrder);
+ }
+ numberToBits = applyEach(numberToFloat32Bits, componentOrder);
+ bitsToNumber = applyEach(float32BitsToNumber, componentOrder);
+ bitsToULPFromZero = applyEach(
+ v => floatBitsToNormalULPFromZero(v, kFloat32Format),
+ componentOrder
+ );
+
+ break;
+ case 16:
+ if (restrictedDepth) {
+ encode = applyEach(v => {
+ assert(v >= 0.0 && v <= 1.0, 'depth out of range');
+ return float16BitsToFloat32(float32ToFloat16Bits(v));
+ }, componentOrder);
+ } else {
+ encode = applyEach(v => float16BitsToFloat32(float32ToFloat16Bits(v)), componentOrder);
+ }
+ numberToBits = applyEach(float32ToFloat16Bits, componentOrder);
+ bitsToNumber = applyEach(float16BitsToFloat32, componentOrder);
+ bitsToULPFromZero = applyEach(
+ v => floatBitsToNormalULPFromZero(v, kFloat16Format),
+ componentOrder
+ );
+
+ break;
+ default:
+ unreachable();
+ }
+
+ const decode = applyEach(identity, componentOrder);
+
+ return {
+ componentOrder,
+ componentInfo: makePerTexelComponent(componentOrder, {
+ dataType: 'float',
+ bitLength,
+ }),
+ encode,
+ decode,
+ pack: components => {
+ switch (bitLength) {
+ case 16:
+ components = applyEach(float32ToFloat16Bits, componentOrder)(components);
+ return packComponents(componentOrder, components, 16, 'uint');
+ case 32:
+ return packComponents(componentOrder, components, bitLength, 'float');
+ default:
+ unreachable();
+ }
+ },
+ unpackBits: data => unpackComponentsBits(componentOrder, data, bitLength),
+ numberToBits,
+ bitsToNumber,
+ bitsToULPFromZero,
+ numericRange: restrictedDepth
+ ? { min: 0, max: 1 }
+ : { min: Number.NEGATIVE_INFINITY, max: Number.POSITIVE_INFINITY },
+ };
+}
+
+const kR = [TexelComponent.R];
+const kRG = [TexelComponent.R, TexelComponent.G];
+const kRGB = [TexelComponent.R, TexelComponent.G, TexelComponent.B];
+const kRGBA = [TexelComponent.R, TexelComponent.G, TexelComponent.B, TexelComponent.A];
+const kBGRA = [TexelComponent.B, TexelComponent.G, TexelComponent.R, TexelComponent.A];
+
+const identity = n => n;
+
+const kFloat11Format = { signed: 0, exponentBits: 5, mantissaBits: 6, bias: 15 };
+const kFloat10Format = { signed: 0, exponentBits: 5, mantissaBits: 5, bias: 15 };
+const kFloat9e5Format = { signed: 0, exponentBits: 5, mantissaBits: 9, bias: 15 };
+
+export const kTexelRepresentationInfo = {
+ ...{
+ r8unorm: makeNormalizedInfo(kR, 8, { signed: false, sRGB: false }),
+ r8snorm: makeNormalizedInfo(kR, 8, { signed: true, sRGB: false }),
+ r8uint: makeIntegerInfo(kR, 8, { signed: false }),
+ r8sint: makeIntegerInfo(kR, 8, { signed: true }),
+ r16uint: makeIntegerInfo(kR, 16, { signed: false }),
+ r16sint: makeIntegerInfo(kR, 16, { signed: true }),
+ r16float: makeFloatInfo(kR, 16),
+ rg8unorm: makeNormalizedInfo(kRG, 8, { signed: false, sRGB: false }),
+ rg8snorm: makeNormalizedInfo(kRG, 8, { signed: true, sRGB: false }),
+ rg8uint: makeIntegerInfo(kRG, 8, { signed: false }),
+ rg8sint: makeIntegerInfo(kRG, 8, { signed: true }),
+ r32uint: makeIntegerInfo(kR, 32, { signed: false }),
+ r32sint: makeIntegerInfo(kR, 32, { signed: true }),
+ r32float: makeFloatInfo(kR, 32),
+ rg16uint: makeIntegerInfo(kRG, 16, { signed: false }),
+ rg16sint: makeIntegerInfo(kRG, 16, { signed: true }),
+ rg16float: makeFloatInfo(kRG, 16),
+ rgba8unorm: makeNormalizedInfo(kRGBA, 8, { signed: false, sRGB: false }),
+ 'rgba8unorm-srgb': makeNormalizedInfo(kRGBA, 8, { signed: false, sRGB: true }),
+ rgba8snorm: makeNormalizedInfo(kRGBA, 8, { signed: true, sRGB: false }),
+ rgba8uint: makeIntegerInfo(kRGBA, 8, { signed: false }),
+ rgba8sint: makeIntegerInfo(kRGBA, 8, { signed: true }),
+ bgra8unorm: makeNormalizedInfo(kBGRA, 8, { signed: false, sRGB: false }),
+ 'bgra8unorm-srgb': makeNormalizedInfo(kBGRA, 8, { signed: false, sRGB: true }),
+ rg32uint: makeIntegerInfo(kRG, 32, { signed: false }),
+ rg32sint: makeIntegerInfo(kRG, 32, { signed: true }),
+ rg32float: makeFloatInfo(kRG, 32),
+ rgba16uint: makeIntegerInfo(kRGBA, 16, { signed: false }),
+ rgba16sint: makeIntegerInfo(kRGBA, 16, { signed: true }),
+ rgba16float: makeFloatInfo(kRGBA, 16),
+ rgba32uint: makeIntegerInfo(kRGBA, 32, { signed: false }),
+ rgba32sint: makeIntegerInfo(kRGBA, 32, { signed: true }),
+ rgba32float: makeFloatInfo(kRGBA, 32),
+ },
+ ...{
+ rgb10a2unorm: {
+ componentOrder: kRGBA,
+ componentInfo: {
+ R: { dataType: 'unorm', bitLength: 10 },
+ G: { dataType: 'unorm', bitLength: 10 },
+ B: { dataType: 'unorm', bitLength: 10 },
+ A: { dataType: 'unorm', bitLength: 2 },
+ },
+ encode: components => {
+ return {
+ R: floatAsNormalizedInteger(components.R ?? unreachable(), 10, false),
+ G: floatAsNormalizedInteger(components.G ?? unreachable(), 10, false),
+ B: floatAsNormalizedInteger(components.B ?? unreachable(), 10, false),
+ A: floatAsNormalizedInteger(components.A ?? unreachable(), 2, false),
+ };
+ },
+ decode: components => {
+ return {
+ R: normalizedIntegerAsFloat(components.R ?? unreachable(), 10, false),
+ G: normalizedIntegerAsFloat(components.G ?? unreachable(), 10, false),
+ B: normalizedIntegerAsFloat(components.B ?? unreachable(), 10, false),
+ A: normalizedIntegerAsFloat(components.A ?? unreachable(), 2, false),
+ };
+ },
+ pack: components =>
+ packComponents(
+ kRGBA,
+ components,
+ {
+ R: 10,
+ G: 10,
+ B: 10,
+ A: 2,
+ },
+ 'uint'
+ ),
+
+ unpackBits: data => unpackComponentsBits(kRGBA, data, { R: 10, G: 10, B: 10, A: 2 }),
+ numberToBits: components => ({
+ R: floatAsNormalizedInteger(components.R ?? unreachable(), 10, false),
+ G: floatAsNormalizedInteger(components.G ?? unreachable(), 10, false),
+ B: floatAsNormalizedInteger(components.B ?? unreachable(), 10, false),
+ A: floatAsNormalizedInteger(components.A ?? unreachable(), 2, false),
+ }),
+ bitsToNumber: components => ({
+ R: normalizedIntegerAsFloat(components.R, 10, false),
+ G: normalizedIntegerAsFloat(components.G, 10, false),
+ B: normalizedIntegerAsFloat(components.B, 10, false),
+ A: normalizedIntegerAsFloat(components.A, 2, false),
+ }),
+ bitsToULPFromZero: components => components,
+ numericRange: { min: 0, max: 1 },
+ },
+ rg11b10ufloat: {
+ componentOrder: kRGB,
+ encode: applyEach(identity, kRGB),
+ decode: applyEach(identity, kRGB),
+ componentInfo: {
+ R: { dataType: 'ufloat', bitLength: 11 },
+ G: { dataType: 'ufloat', bitLength: 11 },
+ B: { dataType: 'ufloat', bitLength: 10 },
+ },
+ pack: components => {
+ const componentsBits = {
+ R: float32ToFloatBits(components.R ?? unreachable(), 0, 5, 6, 15),
+ G: float32ToFloatBits(components.G ?? unreachable(), 0, 5, 6, 15),
+ B: float32ToFloatBits(components.B ?? unreachable(), 0, 5, 5, 15),
+ };
+ return packComponents(
+ kRGB,
+ componentsBits,
+ {
+ R: 11,
+ G: 11,
+ B: 10,
+ },
+ 'uint'
+ );
+ },
+ unpackBits: data => unpackComponentsBits(kRGB, data, { R: 11, G: 11, B: 10 }),
+ numberToBits: components => ({
+ R: numberToFloatBits(components.R ?? unreachable(), kFloat11Format),
+ G: numberToFloatBits(components.G ?? unreachable(), kFloat11Format),
+ B: numberToFloatBits(components.B ?? unreachable(), kFloat10Format),
+ }),
+ bitsToNumber: components => ({
+ R: floatBitsToNumber(components.R, kFloat11Format),
+ G: floatBitsToNumber(components.G, kFloat11Format),
+ B: floatBitsToNumber(components.B, kFloat10Format),
+ }),
+ bitsToULPFromZero: components => ({
+ R: floatBitsToNormalULPFromZero(components.R, kFloat11Format),
+ G: floatBitsToNormalULPFromZero(components.G, kFloat11Format),
+ B: floatBitsToNormalULPFromZero(components.B, kFloat10Format),
+ }),
+ numericRange: { min: 0, max: Number.POSITIVE_INFINITY },
+ },
+ rgb9e5ufloat: {
+ componentOrder: kRGB,
+ componentInfo: makePerTexelComponent(kRGB, {
+ dataType: 'ufloat',
+ bitLength: -1, // Components don't really have a bitLength since the format is packed.
+ }),
+ encode: applyEach(identity, kRGB),
+ decode: applyEach(identity, kRGB),
+ pack: components =>
+ new Uint32Array([
+ packRGB9E5UFloat(
+ components.R ?? unreachable(),
+ components.G ?? unreachable(),
+ components.B ?? unreachable()
+ ),
+ ]).buffer,
+ // For the purpose of unpacking, expand into three "ufloat14" values.
+ unpackBits: data => {
+ // Pretend the exponent part is A so we can use unpackComponentsBits.
+ const parts = unpackComponentsBits(kRGBA, data, { R: 9, G: 9, B: 9, A: 5 });
+ return {
+ R: (parts.A << 9) | parts.R,
+ G: (parts.A << 9) | parts.G,
+ B: (parts.A << 9) | parts.B,
+ };
+ },
+ numberToBits: components => ({
+ R: float32ToFloatBits(components.R ?? unreachable(), 0, 5, 9, 15),
+ G: float32ToFloatBits(components.G ?? unreachable(), 0, 5, 9, 15),
+ B: float32ToFloatBits(components.B ?? unreachable(), 0, 5, 9, 15),
+ }),
+ bitsToNumber: components => ({
+ R: floatBitsToNumber(components.R, kFloat9e5Format),
+ G: floatBitsToNumber(components.G, kFloat9e5Format),
+ B: floatBitsToNumber(components.B, kFloat9e5Format),
+ }),
+ bitsToULPFromZero: components => ({
+ R: floatBitsToNormalULPFromZero(components.R, kFloat9e5Format),
+ G: floatBitsToNormalULPFromZero(components.G, kFloat9e5Format),
+ B: floatBitsToNormalULPFromZero(components.B, kFloat9e5Format),
+ }),
+ numericRange: { min: 0, max: Number.POSITIVE_INFINITY },
+ },
+ depth32float: makeFloatInfo([TexelComponent.Depth], 32, { restrictedDepth: true }),
+ depth16unorm: makeNormalizedInfo([TexelComponent.Depth], 16, { signed: false, sRGB: false }),
+ depth24plus: {
+ componentOrder: [TexelComponent.Depth],
+ componentInfo: { Depth: { dataType: null, bitLength: 24 } },
+ encode: applyEach(() => unreachable('depth24plus cannot be encoded'), [TexelComponent.Depth]),
+ decode: applyEach(() => unreachable('depth24plus cannot be decoded'), [TexelComponent.Depth]),
+ pack: () => unreachable('depth24plus data cannot be packed'),
+ unpackBits: () => unreachable('depth24plus data cannot be unpacked'),
+ numberToBits: () => unreachable('depth24plus has no representation'),
+ bitsToNumber: () => unreachable('depth24plus has no representation'),
+ bitsToULPFromZero: () => unreachable('depth24plus has no representation'),
+ numericRange: { min: 0, max: 1 },
+ },
+ stencil8: makeIntegerInfo([TexelComponent.Stencil], 8, { signed: false }),
+ 'depth32float-stencil8': {
+ componentOrder: [TexelComponent.Depth, TexelComponent.Stencil],
+ componentInfo: {
+ Depth: {
+ dataType: 'float',
+ bitLength: 32,
+ },
+ Stencil: {
+ dataType: 'uint',
+ bitLength: 8,
+ },
+ },
+ encode: components => {
+ assert(components.Stencil !== undefined);
+ assertInIntegerRange(components.Stencil, 8, false);
+ return components;
+ },
+ decode: components => {
+ assert(components.Stencil !== undefined);
+ assertInIntegerRange(components.Stencil, 8, false);
+ return components;
+ },
+ pack: () => unreachable('depth32float-stencil8 data cannot be packed'),
+ unpackBits: () => unreachable('depth32float-stencil8 data cannot be unpacked'),
+ numberToBits: () => unreachable('not implemented'),
+ bitsToNumber: () => unreachable('not implemented'),
+ bitsToULPFromZero: () => unreachable('not implemented'),
+ numericRange: null,
+ },
+ 'depth24plus-stencil8': {
+ componentOrder: [TexelComponent.Depth, TexelComponent.Stencil],
+ componentInfo: {
+ Depth: {
+ dataType: null,
+ bitLength: 24,
+ },
+ Stencil: {
+ dataType: 'uint',
+ bitLength: 8,
+ },
+ },
+ encode: components => {
+ assert(components.Depth === undefined, 'depth24plus cannot be encoded');
+ assert(components.Stencil !== undefined);
+ assertInIntegerRange(components.Stencil, 8, false);
+ return components;
+ },
+ decode: components => {
+ assert(components.Depth === undefined, 'depth24plus cannot be decoded');
+ assert(components.Stencil !== undefined);
+ assertInIntegerRange(components.Stencil, 8, false);
+ return components;
+ },
+ pack: () => unreachable('depth24plus-stencil8 data cannot be packed'),
+ unpackBits: () => unreachable('depth24plus-stencil8 data cannot be unpacked'),
+ numberToBits: () => unreachable('depth24plus-stencil8 has no representation'),
+ bitsToNumber: () => unreachable('depth24plus-stencil8 has no representation'),
+ bitsToULPFromZero: () => unreachable('depth24plus-stencil8 has no representation'),
+ numericRange: null,
+ },
+ },
+};
+
+/**
+ * Get the `ComponentDataType` for a format. All components must have the same type.
+ * @param {UncompressedTextureFormat} format - The input format.
+ * @returns {ComponentDataType} The data of the components.
+ */
+export function getSingleDataType(format) {
+ const infos = Object.values(kTexelRepresentationInfo[format].componentInfo);
+ assert(infos.length > 0);
+ return infos.reduce((acc, cur) => {
+ assert(cur !== undefined);
+ assert(acc === undefined || acc === cur.dataType);
+ return cur.dataType;
+ }, infos[0].dataType);
+}
+
+/**
+ * Get traits for generating code to readback data from a component.
+ * @param {ComponentDataType} dataType - The input component data type.
+ * @returns A dictionary containing the respective `ReadbackTypedArray` and `shaderType`.
+ */
+export function getComponentReadbackTraits(dataType) {
+ switch (dataType) {
+ case 'ufloat':
+ case 'float':
+ case 'unorm':
+ case 'snorm':
+ return {
+ ReadbackTypedArray: Float32Array,
+ shaderType: 'f32',
+ };
+ case 'uint':
+ return {
+ ReadbackTypedArray: Uint32Array,
+ shaderType: 'u32',
+ };
+ case 'sint':
+ return {
+ ReadbackTypedArray: Int32Array,
+ shaderType: 'i32',
+ };
+ default:
+ unreachable();
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js
new file mode 100644
index 0000000000..ce16673fb1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_data.spec.js
@@ -0,0 +1,332 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description =
+ 'Test helpers for texel data produce the expected data in the shader';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+import { kEncodableTextureFormats, kTextureFormatInfo } from '../../capability_info.js';
+import { GPUTest } from '../../gpu_test.js';
+
+import {
+ kTexelRepresentationInfo,
+ getSingleDataType,
+ getComponentReadbackTraits,
+} from './texel_data.js';
+
+export const g = makeTestGroup(GPUTest);
+
+function doTest(t) {
+ const { format } = t.params;
+ const componentData = t.params.componentData;
+
+ const rep = kTexelRepresentationInfo[format];
+ const texelData = rep.pack(componentData);
+ const texture = t.device.createTexture({
+ format,
+ size: [1, 1, 1],
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
+ });
+
+ t.device.queue.writeTexture(
+ { texture },
+ texelData,
+ {
+ bytesPerRow: texelData.byteLength,
+ },
+ [1]
+ );
+
+ const { ReadbackTypedArray, shaderType } = getComponentReadbackTraits(getSingleDataType(format));
+
+ const shader = `
+ @group(0) @binding(0) var tex : texture_2d<${shaderType}>;
+
+ struct Output {
+ ${rep.componentOrder.map(C => `result${C} : ${shaderType},`).join('\n')}
+ };
+ @group(0) @binding(1) var<storage, read_write> output : Output;
+
+ @compute @workgroup_size(1)
+ fn main() {
+ var texel : vec4<${shaderType}> = textureLoad(tex, vec2<i32>(0, 0), 0);
+ ${rep.componentOrder.map(C => `output.result${C} = texel.${C.toLowerCase()};`).join('\n')}
+ return;
+ }`;
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: shader,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const outputBuffer = t.device.createBuffer({
+ size: rep.componentOrder.length * 4,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: texture.createView(),
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: outputBuffer,
+ },
+ },
+ ],
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ t.expectGPUBufferValuesEqual(
+ outputBuffer,
+ new ReadbackTypedArray(
+ rep.componentOrder.map(c => {
+ const value = rep.decode(componentData)[c];
+ assert(value !== undefined);
+ return value;
+ })
+ )
+ );
+}
+
+// Make a test parameter by mapping a format and each component to a texel component
+// data value.
+function makeParam(format, fn) {
+ const rep = kTexelRepresentationInfo[format];
+ return {
+ R: rep.componentInfo.R ? fn(rep.componentInfo.R.bitLength, 0) : undefined,
+ G: rep.componentInfo.G ? fn(rep.componentInfo.G.bitLength, 1) : undefined,
+ B: rep.componentInfo.B ? fn(rep.componentInfo.B.bitLength, 2) : undefined,
+ A: rep.componentInfo.A ? fn(rep.componentInfo.A.bitLength, 3) : undefined,
+ };
+}
+
+g.test('unorm_texel_data_in_shader')
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'unorm'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ const max = bitLength => Math.pow(2, bitLength) - 1;
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+ makeParam(format, bitLength => max(bitLength)),
+
+ // Test a middle value
+ makeParam(format, bitLength => Math.floor(max(bitLength) / 2)),
+
+ // Test mixed values
+ makeParam(format, (bitLength, i) => {
+ const offset = [0.13, 0.63, 0.42, 0.89];
+ return Math.floor(offset[i] * max(bitLength));
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
+
+g.test('snorm_texel_data_in_shader')
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'snorm'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ const max = bitLength => Math.pow(2, bitLength - 1) - 1;
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+ makeParam(format, bitLength => max(bitLength)),
+ makeParam(format, bitLength => -max(bitLength)),
+ makeParam(format, bitLength => -max(bitLength) - 1),
+
+ // Test a middle value
+ makeParam(format, bitLength => Math.floor(max(bitLength) / 2)),
+
+ // Test mixed values
+ makeParam(format, (bitLength, i) => {
+ const offset = [0.13, 0.63, 0.42, 0.89];
+ const range = 2 * max(bitLength);
+ return -max(bitLength) + Math.floor(offset[i] * range);
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
+
+g.test('uint_texel_data_in_shader')
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'uint'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ const max = bitLength => Math.pow(2, bitLength) - 1;
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+ makeParam(format, bitLength => max(bitLength)),
+
+ // Test a middle value
+ makeParam(format, bitLength => Math.floor(max(bitLength) / 2)),
+
+ // Test mixed values
+ makeParam(format, (bitLength, i) => {
+ const offset = [0.13, 0.63, 0.42, 0.89];
+ return Math.floor(offset[i] * max(bitLength));
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
+
+g.test('sint_texel_data_in_shader')
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'sint'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ const max = bitLength => Math.pow(2, bitLength - 1) - 1;
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+ makeParam(format, bitLength => max(bitLength)),
+ makeParam(format, bitLength => -max(bitLength) - 1),
+
+ // Test a middle value
+ makeParam(format, bitLength => Math.floor(max(bitLength) / 2)),
+
+ // Test mixed values
+ makeParam(format, (bitLength, i) => {
+ const offset = [0.13, 0.63, 0.42, 0.89];
+ const range = 2 * max(bitLength);
+ return -max(bitLength) + Math.floor(offset[i] * range);
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
+
+g.test('float_texel_data_in_shader')
+ .desc(
+ `
+TODO: Test NaN, Infinity, -Infinity [1]`
+ )
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'float'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+
+ // [1]: Test NaN, Infinity, -Infinity
+
+ // Test some values
+ makeParam(format, () => 0.1199951171875),
+ makeParam(format, () => 1.4072265625),
+ makeParam(format, () => 24928),
+ makeParam(format, () => -0.1319580078125),
+ makeParam(format, () => -323.25),
+ makeParam(format, () => -7440),
+
+ // Test mixed values
+ makeParam(format, (bitLength, i) => {
+ return [24896, -0.1319580078125, -323.25, -234.375][i];
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
+
+g.test('ufloat_texel_data_in_shader')
+ .desc(
+ `
+TODO: Test NaN, Infinity [1]`
+ )
+ .params(u =>
+ u
+ .combine('format', kEncodableTextureFormats)
+ .filter(({ format }) => {
+ return (
+ kTextureFormatInfo[format].copyDst &&
+ kTextureFormatInfo[format].color &&
+ getSingleDataType(format) === 'ufloat'
+ );
+ })
+ .beginSubcases()
+ .expand('componentData', ({ format }) => {
+ return [
+ // Test extrema
+ makeParam(format, () => 0),
+
+ // [2]: Test NaN, Infinity
+
+ // Test some values
+ makeParam(format, () => 0.119140625),
+ makeParam(format, () => 1.40625),
+ makeParam(format, () => 24896),
+
+ // Test scattered mixed values
+ makeParam(format, (bitLength, i) => {
+ return [24896, 1.40625, 0.119140625, 0.23095703125][i];
+ }),
+
+ // Test mixed values that are close in magnitude.
+ makeParam(format, (bitLength, i) => {
+ return [0.1337890625, 0.17919921875, 0.119140625, 0.125][i];
+ }),
+ ];
+ })
+ )
+ .fn(doTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js
new file mode 100644
index 0000000000..d286afac09
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texel_view.js
@@ -0,0 +1,122 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, memcpy } from '../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import { reifyExtent3D, reifyOrigin3D } from '../unions.js';
+
+import { kTexelRepresentationInfo, makeClampToRange } from './texel_data.js';
+
+/** Function taking some x,y,z coordinates and returning `Readonly<T>`. */
+
+/**
+ * Wrapper to view various representations of texture data in other ways. E.g., can:
+ * - Provide a mapped buffer, containing copied texture data, and read color values.
+ * - Provide a function that generates color values by coordinate, and convert to ULPs-from-zero.
+ *
+ * MAINTENANCE_TODO: Would need some refactoring to support block formats, which could be partially
+ * supported if useful.
+ */
+export class TexelView {
+ /** The GPUTextureFormat of the TexelView. */
+
+ /** Generates the bytes for the texel at the given coordinates. */
+
+ /** Generates the ULPs-from-zero for the texel at the given coordinates. */
+
+ /** Generates the color for the texel at the given coordinates. */
+
+ constructor(format, { bytes, ulpFromZero, color }) {
+ this.format = format;
+ this.bytes = bytes;
+ this.ulpFromZero = ulpFromZero;
+ this.color = color;
+ }
+
+ /**
+ * Produces a TexelView from "linear image data", i.e. the `writeTexture` format. Takes a
+ * reference to the input `subrectData`, so any changes to it will be visible in the TexelView.
+ */
+ static fromTextureDataByReference(
+ format,
+ subrectData,
+ { bytesPerRow, rowsPerImage, subrectOrigin, subrectSize }
+ ) {
+ const origin = reifyOrigin3D(subrectOrigin);
+ const size = reifyExtent3D(subrectSize);
+
+ const info = kTextureFormatInfo[format];
+ assert(info.blockWidth === 1 && info.blockHeight === 1, 'unimplemented for block formats');
+
+ return TexelView.fromTexelsAsBytes(format, coords => {
+ assert(
+ coords.x >= origin.x &&
+ coords.y >= origin.y &&
+ coords.z >= origin.z &&
+ coords.x < origin.x + size.width &&
+ coords.y < origin.y + size.height &&
+ coords.z < origin.z + size.depthOrArrayLayers,
+ 'coordinate out of bounds'
+ );
+
+ const imageOffsetInRows = (coords.z - origin.z) * rowsPerImage;
+ const rowOffset = (imageOffsetInRows + (coords.y - origin.y)) * bytesPerRow;
+ const offset = rowOffset + (coords.x - origin.x) * info.bytesPerBlock;
+
+ // MAINTENANCE_TODO: To support block formats, decode the block and then index into the result.
+ return subrectData.subarray(offset, offset + info.bytesPerBlock);
+ });
+ }
+
+ /** Produces a TexelView from a generator of bytes for individual texel blocks. */
+ static fromTexelsAsBytes(format, generator) {
+ const info = kTextureFormatInfo[format];
+ assert(info.blockWidth === 1 && info.blockHeight === 1, 'unimplemented for block formats');
+
+ const repr = kTexelRepresentationInfo[format];
+ return new TexelView(format, {
+ bytes: generator,
+ ulpFromZero: coords => repr.bitsToULPFromZero(repr.unpackBits(generator(coords))),
+ color: coords => repr.bitsToNumber(repr.unpackBits(generator(coords))),
+ });
+ }
+
+ /** Produces a TexelView from a generator of numeric "color" values for each texel. */
+ static fromTexelsAsColors(format, generator, { clampToFormatRange = false } = {}) {
+ const info = kTextureFormatInfo[format];
+ assert(info.blockWidth === 1 && info.blockHeight === 1, 'unimplemented for block formats');
+
+ if (clampToFormatRange) {
+ const applyClamp = makeClampToRange(format);
+ const oldGenerator = generator;
+ generator = coords => applyClamp(oldGenerator(coords));
+ }
+
+ const repr = kTexelRepresentationInfo[format];
+ return new TexelView(format, {
+ bytes: coords => new Uint8Array(repr.pack(repr.encode(generator(coords)))),
+ ulpFromZero: coords => repr.bitsToULPFromZero(repr.numberToBits(generator(coords))),
+ color: generator,
+ });
+ }
+
+ /** Writes the contents of a TexelView as "linear image data", i.e. the `writeTexture` format. */
+ writeTextureData(
+ subrectData,
+ { bytesPerRow, rowsPerImage, subrectOrigin: subrectOrigin_, subrectSize: subrectSize_ }
+ ) {
+ const subrectOrigin = reifyOrigin3D(subrectOrigin_);
+ const subrectSize = reifyExtent3D(subrectSize_);
+
+ const info = kTextureFormatInfo[this.format];
+ assert(info.blockWidth === 1 && info.blockHeight === 1, 'unimplemented for block formats');
+
+ for (let z = subrectOrigin.z; z < subrectOrigin.z + subrectSize.depthOrArrayLayers; ++z) {
+ for (let y = subrectOrigin.y; y < subrectOrigin.y + subrectSize.height; ++y) {
+ for (let x = subrectOrigin.x; x < subrectOrigin.x + subrectSize.width; ++x) {
+ const start = (z * rowsPerImage + y) * bytesPerRow + x * info.bytesPerBlock;
+ memcpy({ src: this.bytes({ x, y, z }) }, { dst: subrectData, start });
+ }
+ }
+ }
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js
new file mode 100644
index 0000000000..3cb6c2fa90
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.js
@@ -0,0 +1,303 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, ErrorWithExtra, unreachable } from '../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import { generatePrettyTable } from '../pretty_diff_tables.js';
+import { reifyExtent3D, reifyOrigin3D } from '../unions.js';
+
+import { getTextureSubCopyLayout } from './layout.js';
+import { kTexelRepresentationInfo } from './texel_data.js';
+import { TexelView } from './texel_view.js';
+
+function makeTexelViewComparer(format, { actTexelView, expTexelView }, opts) {
+ const {
+ maxIntDiff = 0,
+ maxFractionalDiff,
+ maxDiffULPsForNormFormat,
+ maxDiffULPsForFloatFormat,
+ } = opts;
+
+ assert(maxIntDiff >= 0, 'threshold must be non-negative');
+ if (maxFractionalDiff !== undefined) {
+ assert(maxFractionalDiff >= 0, 'threshold must be non-negative');
+ }
+ if (maxDiffULPsForFloatFormat !== undefined) {
+ assert(maxDiffULPsForFloatFormat >= 0, 'threshold must be non-negative');
+ }
+ if (maxDiffULPsForNormFormat !== undefined) {
+ assert(maxDiffULPsForNormFormat >= 0, 'threshold must be non-negative');
+ }
+
+ const fmtIsInt = format.includes('int');
+ const fmtIsNorm = format.includes('norm');
+ const fmtIsFloat = format.includes('float');
+
+ const tvc = {};
+ if (fmtIsInt) {
+ tvc.predicate = coords =>
+ comparePerComponent(actTexelView.color(coords), expTexelView.color(coords), maxIntDiff);
+ } else if (fmtIsNorm && maxDiffULPsForNormFormat !== undefined) {
+ tvc.predicate = coords =>
+ comparePerComponent(
+ actTexelView.ulpFromZero(coords),
+ expTexelView.ulpFromZero(coords),
+ maxDiffULPsForNormFormat
+ );
+ } else if (fmtIsFloat && maxDiffULPsForFloatFormat !== undefined) {
+ tvc.predicate = coords =>
+ comparePerComponent(
+ actTexelView.ulpFromZero(coords),
+ expTexelView.ulpFromZero(coords),
+ maxDiffULPsForFloatFormat
+ );
+ } else if (maxFractionalDiff !== undefined) {
+ tvc.predicate = coords =>
+ comparePerComponent(
+ actTexelView.color(coords),
+ expTexelView.color(coords),
+ maxFractionalDiff
+ );
+ } else {
+ if (fmtIsNorm) {
+ unreachable('need maxFractionalDiff or maxDiffULPsForNormFormat to compare norm textures');
+ } else if (fmtIsFloat) {
+ unreachable('need maxFractionalDiff or maxDiffULPsForFloatFormat to compare float textures');
+ } else {
+ unreachable();
+ }
+ }
+
+ const repr = kTexelRepresentationInfo[format];
+ if (fmtIsInt) {
+ tvc.tableRows = failedCoords => [
+ [`tolerance ± ${maxIntDiff}`],
+ (function* () {
+ yield* [` diff (act - exp)`, '==', ''];
+ for (const coords of failedCoords) {
+ const act = actTexelView.color(coords);
+ const exp = expTexelView.color(coords);
+ yield repr.componentOrder.map(ch => act[ch] - exp[ch]).join(',');
+ }
+ })(),
+ ];
+ } else if (
+ (fmtIsNorm && maxDiffULPsForNormFormat !== undefined) ||
+ (fmtIsFloat && maxDiffULPsForFloatFormat !== undefined)
+ ) {
+ const toleranceULPs = fmtIsNorm ? maxDiffULPsForNormFormat : maxDiffULPsForFloatFormat;
+ tvc.tableRows = failedCoords => [
+ [`tolerance ± ${toleranceULPs} normal-ULPs`],
+ (function* () {
+ yield* [` diff (act - exp) in normal-ULPs`, '==', ''];
+ for (const coords of failedCoords) {
+ const act = actTexelView.ulpFromZero(coords);
+ const exp = expTexelView.ulpFromZero(coords);
+ yield repr.componentOrder.map(ch => act[ch] - exp[ch]).join(',');
+ }
+ })(),
+ ];
+ } else {
+ assert(maxFractionalDiff !== undefined);
+ tvc.tableRows = failedCoords => [
+ [`tolerance ± ${maxFractionalDiff}`],
+ (function* () {
+ yield* [` diff (act - exp)`, '==', ''];
+ for (const coords of failedCoords) {
+ const act = actTexelView.color(coords);
+ const exp = expTexelView.color(coords);
+ yield repr.componentOrder.map(ch => (act[ch] - exp[ch]).toPrecision(4)).join(',');
+ }
+ })(),
+ ];
+ }
+
+ return tvc;
+}
+
+function comparePerComponent(actual, expected, maxDiff) {
+ return Object.keys(actual).every(key => {
+ const k = key;
+ const act = actual[k];
+ const exp = expected[k];
+ if (exp === undefined) return false;
+ return Math.abs(act - exp) <= maxDiff;
+ });
+}
+
+/** Create a new mappable GPUBuffer, and copy a subrectangle of GPUTexture data into it. */
+function createTextureCopyForMapRead(t, source, copySize, { format }) {
+ const { byteLength, bytesPerRow, rowsPerImage } = getTextureSubCopyLayout(format, copySize, {
+ aspect: source.aspect,
+ });
+
+ const buffer = t.device.createBuffer({
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ size: byteLength,
+ });
+ t.trackForCleanup(buffer);
+
+ const cmd = t.device.createCommandEncoder();
+ cmd.copyTextureToBuffer(source, { buffer, bytesPerRow, rowsPerImage }, copySize);
+ t.device.queue.submit([cmd.finish()]);
+
+ return { buffer, bytesPerRow, rowsPerImage };
+}
+
+function findFailedPixels(
+ format,
+ subrectOrigin,
+ subrectSize,
+ { actTexelView, expTexelView },
+ texelCompareOptions
+) {
+ const comparer = makeTexelViewComparer(
+ format,
+ { actTexelView, expTexelView },
+ texelCompareOptions
+ );
+
+ const lowerCorner = [subrectSize.width, subrectSize.height, subrectSize.depthOrArrayLayers];
+ const upperCorner = [0, 0, 0];
+ const failedPixels = [];
+ for (let z = subrectOrigin.z; z < subrectOrigin.z + subrectSize.depthOrArrayLayers; ++z) {
+ for (let y = subrectOrigin.y; y < subrectOrigin.y + subrectSize.height; ++y) {
+ for (let x = subrectOrigin.x; x < subrectOrigin.x + subrectSize.width; ++x) {
+ const coords = { x, y, z };
+
+ if (!comparer.predicate(coords)) {
+ failedPixels.push(coords);
+ lowerCorner[0] = Math.min(lowerCorner[0], x);
+ lowerCorner[1] = Math.min(lowerCorner[1], y);
+ lowerCorner[2] = Math.min(lowerCorner[2], z);
+ upperCorner[0] = Math.max(upperCorner[0], x);
+ upperCorner[1] = Math.max(upperCorner[1], y);
+ upperCorner[2] = Math.max(upperCorner[2], z);
+ }
+ }
+ }
+ }
+ if (failedPixels.length === 0) {
+ return undefined;
+ }
+
+ const info = kTextureFormatInfo[format];
+ const repr = kTexelRepresentationInfo[format];
+
+ const integerSampleType = info.sampleType === 'uint' || info.sampleType === 'sint';
+ const numberToString = integerSampleType ? n => n.toFixed() : n => n.toPrecision(6);
+
+ const componentOrderStr = repr.componentOrder.join(',') + ':';
+
+ const printCoords = (function* () {
+ yield* [' coords', '==', 'X,Y,Z:'];
+ for (const coords of failedPixels) yield `${coords.x},${coords.y},${coords.z}`;
+ })();
+ const printActualBytes = (function* () {
+ yield* [' act. texel bytes (little-endian)', '==', '0x:'];
+ for (const coords of failedPixels) {
+ yield Array.from(actTexelView.bytes(coords), b => b.toString(16).padStart(2, '0')).join(' ');
+ }
+ })();
+ const printActualColors = (function* () {
+ yield* [' act. colors', '==', componentOrderStr];
+ for (const coords of failedPixels) {
+ const pixel = actTexelView.color(coords);
+ yield `${repr.componentOrder.map(ch => numberToString(pixel[ch])).join(',')}`;
+ }
+ })();
+ const printExpectedColors = (function* () {
+ yield* [' exp. colors', '==', componentOrderStr];
+ for (const coords of failedPixels) {
+ const pixel = expTexelView.color(coords);
+ yield `${repr.componentOrder.map(ch => numberToString(pixel[ch])).join(',')}`;
+ }
+ })();
+ const printActualULPs = (function* () {
+ yield* [' act. normal-ULPs-from-zero', '==', componentOrderStr];
+ for (const coords of failedPixels) {
+ const pixel = actTexelView.ulpFromZero(coords);
+ yield `${repr.componentOrder.map(ch => pixel[ch]).join(',')}`;
+ }
+ })();
+ const printExpectedULPs = (function* () {
+ yield* [` exp. normal-ULPs-from-zero`, '==', componentOrderStr];
+ for (const coords of failedPixels) {
+ const pixel = expTexelView.ulpFromZero(coords);
+ yield `${repr.componentOrder.map(ch => pixel[ch]).join(',')}`;
+ }
+ })();
+
+ const opts = {
+ fillToWidth: 120,
+ numberToString,
+ };
+ return `\
+ between ${lowerCorner} and ${upperCorner} inclusive:
+${generatePrettyTable(opts, [
+ printCoords,
+ printActualBytes,
+ printActualColors,
+ printExpectedColors,
+ printActualULPs,
+ printExpectedULPs,
+ ...comparer.tableRows(failedPixels),
+])}`;
+}
+
+/**
+ * Check the contents of a GPUTexture by reading it back (with copyTextureToBuffer+mapAsync), then
+ * comparing the data with the data in `expTexelView`.
+ *
+ * The actual and expected texture data are both converted to the "NormalULPFromZero" format,
+ * which is a signed number representing how far the number is from zero, in ULPs, skipping
+ * subnormal numbers (where ULP is defined for float, normalized, and integer formats).
+ */
+export async function textureContentIsOKByT2B(
+ t,
+ source,
+ copySize_,
+ { expTexelView },
+ texelCompareOptions
+) {
+ const subrectOrigin = reifyOrigin3D(source.origin ?? [0, 0, 0]);
+ const subrectSize = reifyExtent3D(copySize_);
+ const format = expTexelView.format;
+
+ const { buffer, bytesPerRow, rowsPerImage } = createTextureCopyForMapRead(
+ t,
+ source,
+ subrectSize,
+ { format }
+ );
+
+ await buffer.mapAsync(GPUMapMode.READ);
+ const data = new Uint8Array(buffer.getMappedRange());
+
+ const texelViewConfig = {
+ bytesPerRow,
+ rowsPerImage,
+ subrectOrigin,
+ subrectSize,
+ };
+
+ const actTexelView = TexelView.fromTextureDataByReference(format, data, texelViewConfig);
+
+ const failedPixelsMessage = findFailedPixels(
+ format,
+ subrectOrigin,
+ subrectSize,
+ { actTexelView, expTexelView },
+ texelCompareOptions
+ );
+
+ if (failedPixelsMessage === undefined) {
+ return undefined;
+ }
+
+ const msg = 'Texture level had unexpected contents:\n' + failedPixelsMessage;
+ return new ErrorWithExtra(msg, () => ({
+ expTexelView,
+ // Make a new TexelView with a copy of the data so we can unmap the buffer (debug mode only).
+ actTexelView: TexelView.fromTextureDataByReference(format, data.slice(), texelViewConfig),
+ }));
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.spec.js
new file mode 100644
index 0000000000..00ef1663f9
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/texture/texture_ok.spec.js
@@ -0,0 +1,162 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = 'checkPixels helpers behave as expected against real textures';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { GPUTest } from '../../gpu_test.js';
+
+import { TexelView } from './texel_view.js';
+import { textureContentIsOKByT2B } from './texture_ok.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('float32')
+ .desc(`Basic test that actual/expected must match, for float32.`)
+ .params(u =>
+ u
+ .combineWithParams([
+ { format: 'rgba32float' }, //
+ { format: 'rg32float' },
+ ])
+ .beginSubcases()
+ .combineWithParams([
+ // Expected data is 0.6 in all channels
+ { data: 0.6, opts: { maxFractionalDiff: 0.0000001 }, _ok: true },
+ { data: 0.6, opts: { maxDiffULPsForFloatFormat: 1 }, _ok: true },
+
+ { data: 0.5999, opts: { maxFractionalDiff: 0 }, _ok: false },
+ { data: 0.5999, opts: { maxFractionalDiff: 0.0001001 }, _ok: true },
+
+ { data: 0.6001, opts: { maxFractionalDiff: 0 }, _ok: false },
+ { data: 0.6001, opts: { maxFractionalDiff: 0.0001001 }, _ok: true },
+
+ { data: 0.5999, opts: { maxDiffULPsForFloatFormat: 1677 }, _ok: false },
+ { data: 0.5999, opts: { maxDiffULPsForFloatFormat: 1678 }, _ok: true },
+
+ { data: 0.6001, opts: { maxDiffULPsForFloatFormat: 1676 }, _ok: false },
+ { data: 0.6001, opts: { maxDiffULPsForFloatFormat: 1677 }, _ok: true },
+ ])
+ )
+ .fn(async t => {
+ const { format, data, opts, _ok } = t.params;
+
+ const size = [1, 1];
+ const texture = t.device.createTexture({
+ format,
+ size,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+ t.trackForCleanup(texture);
+ t.device.queue.writeTexture({ texture }, new Float32Array([data, data, data, data]), {}, size);
+
+ const expColor = { R: 0.6, G: 0.6, B: 0.6, A: 0.6 };
+ const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);
+
+ const result = await textureContentIsOKByT2B(t, { texture }, size, { expTexelView }, opts);
+ t.expect((result === undefined) === _ok, `expected ${_ok}, got ${result === undefined}`);
+ });
+
+g.test('norm')
+ .desc(`Basic test that actual/expected must match, for unorm/snorm.`)
+ .params(u =>
+ u
+ .combine('mode', ['bytes', 'colors'])
+ .combineWithParams([
+ { format: 'r8unorm', _maxValue: 255 },
+ { format: 'r8snorm', _maxValue: 127 },
+ ])
+ .beginSubcases()
+ .combineWithParams([
+ // Expected data is [10, 10]
+ { data: [10, 10], _ok: true },
+ { data: [10, 11], _ok: false },
+ { data: [11, 10], _ok: false },
+ { data: [11, 11], _ok: false },
+ ])
+ )
+ .fn(async t => {
+ const { mode, format, _maxValue, data, _ok } = t.params;
+
+ const size = [2, 1];
+ const texture = t.device.createTexture({
+ format,
+ size,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+ t.trackForCleanup(texture);
+ t.device.queue.writeTexture({ texture }, new Int8Array(data), {}, size);
+
+ let expTexelView;
+ switch (mode) {
+ case 'bytes':
+ expTexelView = TexelView.fromTexelsAsBytes(format, coords => new Uint8Array([10]));
+ break;
+ case 'colors':
+ expTexelView = TexelView.fromTexelsAsColors(format, coords => ({ R: 10 / _maxValue }));
+ break;
+ }
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture },
+ size,
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 0 }
+ );
+
+ t.expect((result === undefined) === _ok, result?.message);
+ });
+
+g.test('snorm_min')
+ .desc(
+ `The minimum snorm value has two possible representations (e.g. -127 and -128). Ensure that
+ actual/expected can mismatch in both directions and pass the test.`
+ )
+ .params(u =>
+ u //
+ .combine('mode', ['bytes', 'colors'])
+ .combineWithParams([
+ //
+ { format: 'r8snorm', _maxValue: 127 },
+ ])
+ )
+ .fn(async t => {
+ const { mode, format, _maxValue } = t.params;
+
+ const data = [-_maxValue, -_maxValue - 1];
+
+ const size = [2, 1];
+ const texture = t.device.createTexture({
+ format,
+ size,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+ t.trackForCleanup(texture);
+ t.device.queue.writeTexture({ texture }, new Int8Array(data), {}, size);
+
+ let expTexelView;
+ switch (mode) {
+ case 'bytes':
+ {
+ // Actual value should be [-127,-128], expected value is [-128,-127], both should pass.
+ const exp = [-_maxValue - 1, -_maxValue];
+ expTexelView = TexelView.fromTexelsAsBytes(
+ format,
+ coords => new Uint8Array([exp[coords.x]])
+ );
+ }
+ break;
+ case 'colors':
+ expTexelView = TexelView.fromTexelsAsColors(format, coords => ({ R: -1 }));
+ break;
+ }
+
+ const result = await textureContentIsOKByT2B(
+ t,
+ { texture },
+ size,
+ { expTexelView },
+ { maxDiffULPsForNormFormat: 0 }
+ );
+
+ t.expectOK(result);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/util/unions.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/unions.js
new file mode 100644
index 0000000000..670be89fc8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/util/unions.js
@@ -0,0 +1,42 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ /**
+ * Reifies a `GPUOrigin3D` into a `Required<GPUOrigin3DDict>`.
+ */ export function reifyOrigin3D(val) {
+ if (Symbol.iterator in val) {
+ const v = Array.from(val);
+ return {
+ x: v[0] ?? 0,
+ y: v[1] ?? 0,
+ z: v[2] ?? 0,
+ };
+ } else {
+ const v = val;
+ return {
+ x: v.x ?? 0,
+ y: v.y ?? 0,
+ z: v.z ?? 0,
+ };
+ }
+}
+
+/**
+ * Reifies a `GPUExtent3D` into a `Required<GPUExtent3DDict>`.
+ */
+export function reifyExtent3D(val) {
+ if (Symbol.iterator in val) {
+ const v = Array.from(val);
+ return {
+ width: v[0] ?? 1,
+ height: v[1] ?? 1,
+ depthOrArrayLayers: v[2] ?? 1,
+ };
+ } else {
+ const v = val;
+ return {
+ width: v.width ?? 1,
+ height: v.height ?? 1,
+ depthOrArrayLayers: v.depthOrArrayLayers ?? 1,
+ };
+ }
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js
new file mode 100644
index 0000000000..900158ca76
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/configure.spec.js
@@ -0,0 +1,425 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for GPUCanvasContext.configure.
+
+TODO:
+- Test colorSpace
+- Test viewFormats
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+import {
+ kAllTextureFormats,
+ kCanvasTextureFormats,
+ kTextureUsages,
+ filterFormatsByFeature,
+ kFeaturesForFormats,
+ kTextureFormats,
+ viewCompatible,
+} from '../../capability_info.js';
+import { GPUConst } from '../../constants.js';
+import { GPUTest } from '../../gpu_test.js';
+import { kAllCanvasTypes, createCanvas } from '../../util/create_elements.js';
+
+export const g = makeTestGroup(GPUTest);
+
+g.test('defaults')
+ .desc(
+ `
+ Ensure that the defaults for GPUCanvasConfiguration are correct.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const { canvasType } = t.params;
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ });
+
+ const currentTexture = ctx.getCurrentTexture();
+ t.expect(currentTexture.format === 'rgba8unorm');
+ t.expect(currentTexture.usage === GPUTextureUsage.RENDER_ATTACHMENT);
+ t.expect(currentTexture.dimension === '2d');
+ t.expect(currentTexture.width === canvas.width);
+ t.expect(currentTexture.height === canvas.height);
+ t.expect(currentTexture.depthOrArrayLayers === 1);
+ t.expect(currentTexture.mipLevelCount === 1);
+ t.expect(currentTexture.sampleCount === 1);
+ });
+
+g.test('device')
+ .desc(
+ `
+ Ensure that configure reacts appropriately to various device states.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const { canvasType } = t.params;
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ // Calling configure without a device should throw.
+ t.shouldThrow(true, () => {
+ ctx.configure({
+ format: 'rgba8unorm',
+ });
+ });
+
+ // Device is not configured, so getCurrentTexture will throw.
+ t.shouldThrow(true, () => {
+ ctx.getCurrentTexture();
+ });
+
+ // Calling configure with a device should succeed.
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ });
+
+ // getCurrentTexture will succeed with a valid device.
+ ctx.getCurrentTexture();
+
+ // Unconfiguring should cause the device to be cleared.
+ ctx.unconfigure();
+ t.shouldThrow(true, () => {
+ ctx.getCurrentTexture();
+ });
+
+ // Should be able to successfully configure again after unconfiguring.
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ });
+ ctx.getCurrentTexture();
+ });
+
+g.test('format')
+ .desc(
+ `
+ Ensure that only valid texture formats are allowed when calling configure.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('format', kAllTextureFormats)
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
+ })
+ .fn(async t => {
+ const { canvasType, format } = t.params;
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ // Would prefer to use kCanvasTextureFormats.includes(format), but that's giving TS errors.
+ let validFormat = false;
+ for (const canvasFormat of kCanvasTextureFormats) {
+ if (format === canvasFormat) {
+ validFormat = true;
+ break;
+ }
+ }
+
+ t.expectValidationError(() => {
+ ctx.configure({
+ device: t.device,
+ format,
+ });
+ }, !validFormat);
+
+ t.expectValidationError(() => {
+ // Should always return a texture, whether the configured format was valid or not.
+ const currentTexture = ctx.getCurrentTexture();
+ t.expect(currentTexture instanceof GPUTexture);
+ }, !validFormat);
+ });
+
+g.test('usage')
+ .desc(
+ `
+ Ensure that getCurrentTexture returns a texture with the configured usages.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .beginSubcases()
+ .expand('usage', p => {
+ const usageSet = new Set();
+ for (const usage0 of kTextureUsages) {
+ for (const usage1 of kTextureUsages) {
+ usageSet.add(usage0 | usage1);
+ }
+ }
+ return usageSet;
+ })
+ )
+ .fn(async t => {
+ const { canvasType, usage } = t.params;
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ usage,
+ });
+
+ const currentTexture = ctx.getCurrentTexture();
+ t.expect(currentTexture instanceof GPUTexture);
+ t.expect(currentTexture.usage === usage);
+
+ // Try to use the texture with the given usage
+
+ if (usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) {
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: currentTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ if (usage & GPUConst.TextureUsage.TEXTURE_BINDING) {
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ texture: {},
+ },
+ ],
+ });
+
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: currentTexture.createView(),
+ },
+ ],
+ });
+ }
+
+ if (usage & GPUConst.TextureUsage.STORAGE_BINDING) {
+ const bgl = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ storageTexture: { access: 'write-only', format: currentTexture.format },
+ },
+ ],
+ });
+
+ t.device.createBindGroup({
+ layout: bgl,
+ entries: [
+ {
+ binding: 0,
+ resource: currentTexture.createView(),
+ },
+ ],
+ });
+ }
+
+ if (usage & GPUConst.TextureUsage.COPY_DST) {
+ const rgbaData = new Uint8Array([255, 0, 0, 255]);
+
+ t.device.queue.writeTexture({ texture: currentTexture }, rgbaData, {}, [1, 1, 1]);
+ }
+
+ if (usage & GPUConst.TextureUsage.COPY_SRC) {
+ const size = [currentTexture.width, currentTexture.height, 1];
+ const dstTexture = t.device.createTexture({
+ format: currentTexture.format,
+ usage: GPUTextureUsage.COPY_DST,
+ size,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyTextureToTexture({ texture: currentTexture }, { texture: dstTexture }, size);
+ t.device.queue.submit([encoder.finish()]);
+ }
+ });
+
+g.test('alpha_mode')
+ .desc(
+ `
+ Ensure that all valid alphaMode values are allowed when calling configure.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .beginSubcases()
+ .combine('alphaMode', ['opaque', 'premultiplied'])
+ )
+ .fn(async t => {
+ const { canvasType, alphaMode } = t.params;
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ alphaMode,
+ });
+
+ const currentTexture = ctx.getCurrentTexture();
+ t.expect(currentTexture instanceof GPUTexture);
+ });
+
+g.test('size_zero_before_configure')
+ .desc(`Ensure a validation error is raised in configure() if the size of the canvas is zero.`)
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('zeroDimension', ['width', 'height'])
+ )
+ .fn(t => {
+ const { canvasType, zeroDimension } = t.params;
+ const canvas = createCanvas(t, canvasType, 1, 1);
+ canvas[zeroDimension] = 0;
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ // Validation error, the canvas size is 0 which doesn't make a valid GPUTextureDescriptor.
+ t.expectValidationError(() => {
+ ctx.configure({
+ device: t.device,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ });
+
+ canvas[zeroDimension] = 1;
+
+ // The size being incorrect doesn't make for an invalid configuration. Now that it is fixed
+ // getting textures from the canvas should work.
+ const currentTexture = ctx.getCurrentTexture();
+
+ // Try rendering to it even!
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: currentTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ });
+
+g.test('size_zero_after_configure')
+ .desc(
+ `Ensure a validation error is raised after configure() if the size of the canvas becomes zero.`
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('zeroDimension', ['width', 'height'])
+ )
+ .fn(t => {
+ const { canvasType, zeroDimension } = t.params;
+ const canvas = createCanvas(t, canvasType, 1, 1);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: t.device,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ canvas[zeroDimension] = 0;
+
+ // The size is incorrect, we should be getting an error texture and a validation error.
+ let currentTexture;
+ t.expectValidationError(() => {
+ currentTexture = ctx.getCurrentTexture();
+ });
+
+ t.expect(currentTexture[zeroDimension] === 0);
+
+ // Using the texture should produce a validation error.
+ t.expectValidationError(() => {
+ currentTexture.createView();
+ });
+ });
+
+g.test('viewFormats')
+ .desc(
+ `Test the validation that viewFormats are compatible with the format (for all canvas format / view formats)`
+ )
+ .params(u =>
+ u
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('format', kCanvasTextureFormats)
+ .combine('viewFormatFeature', kFeaturesForFormats)
+ .beginSubcases()
+ .expand('viewFormat', ({ viewFormatFeature }) =>
+ filterFormatsByFeature(viewFormatFeature, kTextureFormats)
+ )
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase([t.params.viewFormatFeature]);
+ })
+ .fn(t => {
+ const { canvasType, format, viewFormat } = t.params;
+ const canvas = createCanvas(t, canvasType, 1, 1);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ const compatible = viewCompatible(format, viewFormat);
+
+ // Test configure() produces an error if the formats aren't compatible.
+ t.expectValidationError(() => {
+ ctx.configure({
+ device: t.device,
+ format,
+ viewFormats: [viewFormat],
+ });
+ }, !compatible);
+
+ // Likewise for getCurrentTexture().
+ let currentTexture;
+ t.expectValidationError(() => {
+ currentTexture = ctx.getCurrentTexture();
+ }, !compatible);
+
+ // The returned texture is an error texture.
+ t.expectValidationError(() => {
+ currentTexture.createView();
+ }, !compatible);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/context_creation.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/context_creation.spec.js
new file mode 100644
index 0000000000..de078d3fbd
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/context_creation.spec.js
@@ -0,0 +1,48 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for canvas context creation.
+
+Note there are no context creation attributes for WebGPU (as of this writing).
+Options are configured in configure() instead.
+`;
+import { Fixture } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+export const g = makeTestGroup(Fixture);
+
+g.test('return_type')
+ .desc(
+ `Test the return type of getContext for WebGPU.
+
+ TODO: Test OffscreenCanvas made from transferControlToOffscreen.`
+ )
+ .params(u =>
+ u //
+ .combine('offscreen', [false, true])
+ .beginSubcases()
+ .combine('attributes', [undefined, {}])
+ )
+ .fn(async t => {
+ let canvas;
+ if (t.params.offscreen) {
+ if (typeof OffscreenCanvas === 'undefined') {
+ // Skip if the current context doesn't have OffscreenCanvas (e.g. Node).
+ t.skip('OffscreenCanvas is not available in this context');
+ }
+
+ canvas = new OffscreenCanvas(10, 10);
+ } else {
+ if (typeof document === 'undefined') {
+ // Skip if there is no document (Workers, Node)
+ t.skip('DOM is not available to create canvas element');
+ }
+
+ canvas = document.createElement('canvas', t.params.attributes);
+ canvas.width = 10;
+ canvas.height = 10;
+ }
+
+ const ctx = canvas.getContext('webgpu');
+ t.expect(ctx instanceof GPUCanvasContext);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js
new file mode 100644
index 0000000000..552363ead7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getCurrentTexture.spec.js
@@ -0,0 +1,263 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for GPUCanvasContext.getCurrentTexture.
+`;
+import { SkipTestCase } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../common/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+import { kAllCanvasTypes, createCanvas } from '../../util/create_elements.js';
+
+class GPUContextTest extends GPUTest {
+ initCanvasContext(canvasType = 'onscreen') {
+ const canvas = createCanvas(this, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: this.device,
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+
+ return ctx;
+ }
+}
+
+export const g = makeTestGroup(GPUContextTest);
+
+g.test('configured')
+ .desc(
+ `Checks that calling getCurrentTexture requires the context to be configured first, and
+ that each call to configure causes getCurrentTexture to return a new texture.`
+ )
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const canvas = createCanvas(t, t.params.canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ // Calling getCurrentTexture prior to configuration should throw an exception.
+ t.shouldThrow(true, () => {
+ ctx.getCurrentTexture();
+ });
+
+ // Once the context has been configured getCurrentTexture can be called.
+ ctx.configure({
+ device: t.device,
+ format: 'rgba8unorm',
+ });
+
+ let prevTexture = ctx.getCurrentTexture();
+
+ // Calling configure again with different values will change the texture returned.
+ ctx.configure({
+ device: t.device,
+ format: 'bgra8unorm',
+ });
+
+ let currentTexture = ctx.getCurrentTexture();
+ t.expect(prevTexture !== currentTexture);
+ prevTexture = currentTexture;
+
+ // Calling configure again with the same values will still change the texture returned.
+ ctx.configure({
+ device: t.device,
+ format: 'bgra8unorm',
+ });
+
+ currentTexture = ctx.getCurrentTexture();
+ t.expect(prevTexture !== currentTexture);
+ prevTexture = currentTexture;
+
+ // Calling getCurrentTexture after calling unconfigure should throw an exception.
+ ctx.unconfigure();
+
+ t.shouldThrow(true, () => {
+ ctx.getCurrentTexture();
+ });
+ });
+
+g.test('single_frames')
+ .desc(`Checks that the value of getCurrentTexture is consistent within a single frame.`)
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const ctx = t.initCanvasContext(t.params.canvasType);
+ const frameTexture = ctx.getCurrentTexture();
+
+ // Calling getCurrentTexture a second time returns the same texture.
+ t.expect(frameTexture === ctx.getCurrentTexture());
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: frameTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // Calling getCurrentTexture after performing some work on the texture returns the same texture.
+ t.expect(frameTexture === ctx.getCurrentTexture());
+
+ // Ensure that getCurrentTexture does not clear the texture.
+ t.expectSingleColor(frameTexture, frameTexture.format, {
+ size: [frameTexture.width, frameTexture.height, 1],
+ exp: { R: 1, G: 0, B: 0, A: 1 },
+ });
+
+ frameTexture.destroy();
+
+ // Calling getCurrentTexture after destroying the texture still returns the same texture.
+ t.expect(frameTexture === ctx.getCurrentTexture());
+ });
+
+g.test('multiple_frames')
+ .desc(`Checks that the value of getCurrentTexture differs across multiple frames.`)
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ .beginSubcases()
+ .combine('clearTexture', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { canvasType } = t.params;
+ if (canvasType === 'offscreen' && !('transferToImageBitmap' in OffscreenCanvas.prototype)) {
+ throw new SkipTestCase('transferToImageBitmap not supported');
+ }
+ })
+ .fn(async t => {
+ const { canvasType, clearTexture } = t.params;
+
+ return new Promise(resolve => {
+ const ctx = t.initCanvasContext(canvasType);
+ let prevTexture;
+ let frameCount = 0;
+
+ async function frameCheck() {
+ const currentTexture = ctx.getCurrentTexture();
+
+ if (prevTexture) {
+ // Ensure that each frame a new texture object is returned.
+ t.expect(currentTexture !== prevTexture);
+
+ // Ensure that texture contents are transparent black.
+ t.expectSingleColor(currentTexture, currentTexture.format, {
+ size: [currentTexture.width, currentTexture.height, 1],
+ exp: { R: 0, G: 0, B: 0, A: 0 },
+ });
+ }
+
+ if (clearTexture) {
+ // Clear the texture to test that texture contents don't carry over from frame to frame.
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: currentTexture.createView(),
+ clearValue: [1.0, 0.0, 0.0, 1.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ prevTexture = currentTexture;
+
+ if (frameCount++ < 5) {
+ // Which method will be used to begin a new "frame"?
+ switch (canvasType) {
+ case 'onscreen':
+ requestAnimationFrame(frameCheck);
+ break;
+ case 'offscreen': {
+ ctx.canvas.transferToImageBitmap();
+ // The beginning of frameCheck runs immediately (in the same task), so this
+ // verifies the state has changed synchronously.
+ void frameCheck();
+ break;
+ }
+ default:
+ unreachable();
+ }
+ } else {
+ resolve();
+ }
+ }
+
+ void frameCheck();
+ });
+ });
+
+g.test('resize')
+ .desc(`Checks the value of getCurrentTexture differs when the canvas is resized.`)
+ .params(u =>
+ u //
+ .combine('canvasType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const ctx = t.initCanvasContext(t.params.canvasType);
+ let prevTexture = ctx.getCurrentTexture();
+
+ // Trigger a resize by changing the width.
+ ctx.canvas.width = 4;
+
+ // When the canvas resizes the texture returned by getCurrentTexture should immediately begin
+ // returning a new texture matching the update dimensions.
+ let currentTexture = ctx.getCurrentTexture();
+ t.expect(prevTexture !== currentTexture);
+ t.expect(currentTexture.width === ctx.canvas.width);
+ t.expect(currentTexture.height === ctx.canvas.height);
+
+ // The width and height of the previous texture should remain unchanged.
+ t.expect(prevTexture.width === 2);
+ t.expect(prevTexture.height === 2);
+ prevTexture = currentTexture;
+
+ // Ensure that texture contents are transparent black.
+ t.expectSingleColor(currentTexture, currentTexture.format, {
+ size: [currentTexture.width, currentTexture.height, 1],
+ exp: { R: 0, G: 0, B: 0, A: 0 },
+ });
+
+ // Trigger a resize by changing the height.
+ ctx.canvas.height = 4;
+
+ // Check to ensure the texture is resized again.
+ currentTexture = ctx.getCurrentTexture();
+ t.expect(prevTexture !== currentTexture);
+ t.expect(currentTexture.width === ctx.canvas.width);
+ t.expect(currentTexture.height === ctx.canvas.height);
+ t.expect(prevTexture.width === 4);
+ t.expect(prevTexture.height === 2);
+ prevTexture = currentTexture;
+
+ // Ensure that texture contents are transparent black.
+ t.expectSingleColor(currentTexture, currentTexture.format, {
+ size: [currentTexture.width, currentTexture.height, 1],
+ exp: { R: 0, G: 0, B: 0, A: 0 },
+ });
+
+ // Simply setting the canvas width and height values to their current values should not trigger
+ // a change in the texture.
+ ctx.canvas.width = 4;
+ ctx.canvas.height = 4;
+
+ currentTexture = ctx.getCurrentTexture();
+ t.expect(prevTexture === currentTexture);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.js
new file mode 100644
index 0000000000..64ecf72a4b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/getPreferredCanvasFormat.spec.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for navigator.gpu.getPreferredCanvasFormat.
+`;
+import { Fixture } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+
+export const g = makeTestGroup(Fixture);
+
+g.test('value')
+ .desc(
+ `
+ Ensure getPreferredCanvasFormat returns one of the valid values.
+ `
+ )
+ .fn(async t => {
+ const preferredFormat = navigator.gpu.getPreferredCanvasFormat();
+ t.expect(preferredFormat === 'bgra8unorm' || preferredFormat === 'rgba8unorm');
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
new file mode 100644
index 0000000000..4dbd76626a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
@@ -0,0 +1,464 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for readback from WebGPU Canvas.
+
+This includes testing that colorSpace makes it through from the WebGPU canvas
+to the form of copy (toDataURL, toBlob, ImageBitmap, drawImage)
+
+The color space support is tested by drawing the readback form of the WebGPU
+canvas into a 2D canvas of a different color space via drawImage (A). Another
+2D canvas is created with the same source data and color space as the WebGPU
+canvas and also drawn into another 2D canvas of a different color space (B).
+The contents of A and B should match.
+
+TODO: implement all canvas types, see TODO on kCanvasTypes.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert, raceWithRejectOnTimeout, unreachable } from '../../../common/util/util.js';
+import {
+ kCanvasAlphaModes,
+ kCanvasColorSpaces,
+ kCanvasTextureFormats,
+} from '../../capability_info.js';
+import { GPUTest } from '../../gpu_test.js';
+import { checkElementsEqual } from '../../util/check_contents.js';
+import { kAllCanvasTypes, createCanvas, createOnscreenCanvas } from '../../util/create_elements.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// We choose 0x66 as the value for each color and alpha channel
+// 0x66 / 0xff = 0.4
+// Given a pixel value of RGBA = (0x66, 0, 0, 0x66) in the source WebGPU canvas,
+// For alphaMode = opaque, the copy output should be RGBA = (0x66, 0, 0, 0xff)
+// For alphaMode = premultiplied, the copy output should be RGBA = (0xff, 0, 0, 0x66)
+const kPixelValue = 0x66;
+const kPixelValueFloat = 0x66 / 0xff; // 0.4
+
+// Use four pixels rectangle for the test:
+// blue: top-left;
+// green: top-right;
+// red: bottom-left;
+// yellow: bottom-right;
+const expect = {
+ opaque: new Uint8ClampedArray([
+ 0,
+ 0,
+ kPixelValue,
+ 0xff, // blue
+ 0,
+ kPixelValue,
+ 0,
+ 0xff, // green
+ kPixelValue,
+ 0,
+ 0,
+ 0xff, // red
+ kPixelValue,
+ kPixelValue,
+ 0,
+ 0xff, // yellow
+ ]),
+
+ premultiplied: new Uint8ClampedArray([
+ 0,
+ 0,
+ 0xff,
+ kPixelValue, // blue
+ 0,
+ 0xff,
+ 0,
+ kPixelValue, // green
+ 0xff,
+ 0,
+ 0,
+ kPixelValue, // red
+ 0xff,
+ 0xff,
+ 0,
+ kPixelValue, // yellow
+ ]),
+};
+
+async function initWebGPUCanvasContent(t, format, alphaMode, colorSpace, canvasType) {
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ ctx.configure({
+ device: t.device,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ alphaMode,
+ colorSpace,
+ });
+
+ const canvasTexture = ctx.getCurrentTexture();
+ const tempTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depthOrArrayLayers: 1 },
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const tempTextureView = tempTexture.createView();
+ const encoder = t.device.createCommandEncoder();
+
+ const clearOnePixel = (origin, color) => {
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ { view: tempTextureView, clearValue: color, loadOp: 'clear', storeOp: 'store' },
+ ],
+ });
+ pass.end();
+ encoder.copyTextureToTexture(
+ { texture: tempTexture },
+ { texture: canvasTexture, origin },
+ { width: 1, height: 1 }
+ );
+ };
+
+ clearOnePixel([0, 0], [0, 0, kPixelValueFloat, kPixelValueFloat]);
+ clearOnePixel([1, 0], [0, kPixelValueFloat, 0, kPixelValueFloat]);
+ clearOnePixel([0, 1], [kPixelValueFloat, 0, 0, kPixelValueFloat]);
+ clearOnePixel([1, 1], [kPixelValueFloat, kPixelValueFloat, 0, kPixelValueFloat]);
+
+ t.device.queue.submit([encoder.finish()]);
+ tempTexture.destroy();
+
+ return canvas;
+}
+
+function drawImageSourceIntoCanvas(t, image, colorSpace) {
+ const canvas = createOnscreenCanvas(t, 2, 2);
+ const ctx = canvas.getContext('2d', { colorSpace });
+ assert(ctx !== null);
+ ctx.drawImage(image, 0, 0);
+ return ctx;
+}
+
+function checkImageResultWithSameColorSpaceCanvas(t, image, sourceColorSpace, expect) {
+ const ctx = drawImageSourceIntoCanvas(t, image, sourceColorSpace);
+ readPixelsFrom2DCanvasAndCompare(t, ctx, expect);
+}
+
+function checkImageResultWithDifferentColorSpaceCanvas(t, image, sourceColorSpace, sourceData) {
+ const destinationColorSpace = sourceColorSpace === 'srgb' ? 'display-p3' : 'srgb';
+
+ // draw the WebGPU derived data into a canvas
+ const fromWebGPUCtx = drawImageSourceIntoCanvas(t, image, destinationColorSpace);
+
+ // create a 2D canvas with the same source data in the same color space as the WebGPU
+ // canvas
+ const source2DCanvas = createOnscreenCanvas(t, 2, 2);
+ const source2DCtx = source2DCanvas.getContext('2d', { colorSpace: sourceColorSpace });
+ assert(source2DCtx !== null);
+ const imgData = source2DCtx.getImageData(0, 0, 2, 2);
+ imgData.data.set(sourceData);
+ source2DCtx.putImageData(imgData, 0, 0);
+
+ // draw the source 2D canvas into another 2D canvas with the destination color space and
+ // then pull out the data. This result should be the same as the WebGPU derived data
+ // written to a 2D canvas of the same destination color space.
+ const from2DCtx = drawImageSourceIntoCanvas(t, source2DCanvas, destinationColorSpace);
+ const expect = from2DCtx.getImageData(0, 0, 2, 2).data;
+
+ readPixelsFrom2DCanvasAndCompare(t, fromWebGPUCtx, expect);
+}
+
+function checkImageResult(t, image, sourceColorSpace, expect) {
+ checkImageResultWithSameColorSpaceCanvas(t, image, sourceColorSpace, expect);
+ checkImageResultWithDifferentColorSpaceCanvas(t, image, sourceColorSpace, expect);
+}
+
+function readPixelsFrom2DCanvasAndCompare(t, ctx, expect) {
+ const actual = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height).data;
+
+ t.expectOK(checkElementsEqual(actual, expect));
+}
+
+g.test('onscreenCanvas,snapshot')
+ .desc(
+ `
+ Ensure snapshot of canvas with WebGPU context is correct with
+ - various WebGPU canvas texture formats
+ - WebGPU canvas alpha mode = {"opaque", "premultiplied"}
+ - colorSpace = {"srgb", "display-p3"}
+ - snapshot methods = {convertToBlob, transferToImageBitmap, createImageBitmap}
+
+ TODO: Snapshot canvas to jpeg, webp and other mime type and
+ different quality. Maybe we should test them in reftest.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kCanvasTextureFormats)
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('colorSpace', kCanvasColorSpaces)
+ .combine('snapshotType', ['toDataURL', 'toBlob', 'imageBitmap'])
+ )
+ .fn(async t => {
+ const canvas = await initWebGPUCanvasContent(
+ t,
+ t.params.format,
+ t.params.alphaMode,
+ t.params.colorSpace,
+ 'onscreen'
+ );
+
+ let snapshot;
+ switch (t.params.snapshotType) {
+ case 'toDataURL': {
+ const url = canvas.toDataURL();
+ const img = new Image(canvas.width, canvas.height);
+ img.src = url;
+ await raceWithRejectOnTimeout(img.decode(), 5000, 'load image timeout');
+ snapshot = img;
+ break;
+ }
+ case 'toBlob': {
+ const blobFromCanvas = new Promise(resolve => {
+ canvas.toBlob(blob => resolve(blob));
+ });
+ const blob = await blobFromCanvas;
+ const url = URL.createObjectURL(blob);
+ const img = new Image(canvas.width, canvas.height);
+ img.src = url;
+ await raceWithRejectOnTimeout(img.decode(), 5000, 'load image timeout');
+ snapshot = img;
+ break;
+ }
+ case 'imageBitmap': {
+ snapshot = await createImageBitmap(canvas);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ checkImageResult(t, snapshot, t.params.colorSpace, expect[t.params.alphaMode]);
+ });
+
+g.test('offscreenCanvas,snapshot')
+ .desc(
+ `
+ Ensure snapshot of offscreenCanvas with WebGPU context is correct with
+ - various WebGPU canvas texture formats
+ - WebGPU canvas alpha mode = {"opaque", "premultiplied"}
+ - colorSpace = {"srgb", "display-p3"}
+ - snapshot methods = {convertToBlob, transferToImageBitmap, createImageBitmap}
+
+ TODO: Snapshot offscreenCanvas to jpeg, webp and other mime type and
+ different quality. Maybe we should test them in reftest.
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kCanvasTextureFormats)
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('colorSpace', kCanvasColorSpaces)
+ .combine('snapshotType', ['convertToBlob', 'transferToImageBitmap', 'imageBitmap'])
+ )
+ .fn(async t => {
+ const offscreenCanvas = await initWebGPUCanvasContent(
+ t,
+ t.params.format,
+ t.params.alphaMode,
+ t.params.colorSpace,
+ 'offscreen'
+ );
+
+ let snapshot;
+ switch (t.params.snapshotType) {
+ case 'convertToBlob': {
+ if (typeof offscreenCanvas.convertToBlob === undefined) {
+ t.skip("Browser doesn't support OffscreenCanvas.convertToBlob");
+ return;
+ }
+ const blob = await offscreenCanvas.convertToBlob();
+ const url = URL.createObjectURL(blob);
+ const img = new Image(offscreenCanvas.width, offscreenCanvas.height);
+ img.src = url;
+ await raceWithRejectOnTimeout(img.decode(), 5000, 'load image timeout');
+ snapshot = img;
+ break;
+ }
+ case 'transferToImageBitmap': {
+ if (typeof offscreenCanvas.transferToImageBitmap === undefined) {
+ t.skip("Browser doesn't support OffscreenCanvas.transferToImageBitmap");
+ return;
+ }
+ snapshot = offscreenCanvas.transferToImageBitmap();
+ break;
+ }
+ case 'imageBitmap': {
+ snapshot = await createImageBitmap(offscreenCanvas);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ checkImageResult(t, snapshot, t.params.colorSpace, expect[t.params.alphaMode]);
+ });
+
+g.test('onscreenCanvas,uploadToWebGL')
+ .desc(
+ `
+ Ensure upload WebGPU context canvas to webgl texture is correct with
+ - various WebGPU canvas texture formats
+ - WebGPU canvas alpha mode = {"opaque", "premultiplied"}
+ - upload methods = {texImage2D, texSubImage2D}
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kCanvasTextureFormats)
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('webgl', ['webgl', 'webgl2'])
+ .combine('upload', ['texImage2D', 'texSubImage2D'])
+ )
+ .fn(async t => {
+ const { format, webgl, upload } = t.params;
+ const canvas = await initWebGPUCanvasContent(t, format, t.params.alphaMode, 'srgb', 'onscreen');
+
+ const expectCanvas = createOnscreenCanvas(t, canvas.width, canvas.height);
+ const gl = expectCanvas.getContext(webgl);
+ if (gl === null) {
+ return;
+ }
+
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ switch (upload) {
+ case 'texImage2D': {
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+ break;
+ }
+ case 'texSubImage2D': {
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ canvas.width,
+ canvas.height,
+ 0,
+ gl.RGBA,
+ gl.UNSIGNED_BYTE,
+ null
+ );
+
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
+ break;
+ }
+ default:
+ unreachable();
+ }
+
+ const fb = gl.createFramebuffer();
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ const pixels = new Uint8Array(canvas.width * canvas.height * 4);
+ gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ const actual = new Uint8ClampedArray(pixels);
+
+ t.expectOK(checkElementsEqual(actual, expect[t.params.alphaMode]));
+ });
+
+g.test('drawTo2DCanvas')
+ .desc(
+ `
+ Ensure draw WebGPU context canvas to 2d context canvas/offscreenCanvas is correct with
+ - various WebGPU canvas texture formats
+ - WebGPU canvas alpha mode = {"opaque", "premultiplied"}
+ - colorSpace = {"srgb", "display-p3"}
+ - WebGPU canvas type = {"onscreen", "offscreen"}
+ - 2d canvas type = {"onscreen", "offscreen"}
+ `
+ )
+ .params(u =>
+ u //
+ .combine('format', kCanvasTextureFormats)
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('colorSpace', kCanvasColorSpaces)
+ .combine('webgpuCanvasType', kAllCanvasTypes)
+ .combine('canvas2DType', kAllCanvasTypes)
+ )
+ .fn(async t => {
+ const { format, webgpuCanvasType, alphaMode, colorSpace, canvas2DType } = t.params;
+
+ const canvas = await initWebGPUCanvasContent(
+ t,
+ format,
+ alphaMode,
+ colorSpace,
+ webgpuCanvasType
+ );
+
+ const expectCanvas = createCanvas(t, canvas2DType, canvas.width, canvas.height);
+ const ctx = expectCanvas.getContext('2d');
+ if (ctx === null) {
+ t.skip(canvas2DType + ' canvas cannot get 2d context');
+ return;
+ }
+
+ ctx.drawImage(canvas, 0, 0);
+ readPixelsFrom2DCanvasAndCompare(t, ctx, expect[t.params.alphaMode]);
+ });
+
+g.test('transferToImageBitmap_unconfigured_nonzero_size')
+ .desc(
+ `Regression test for a crash when calling transferImageBitmap on an unconfigured. Case where the canvas is not empty`
+ )
+ .fn(t => {
+ const canvas = createCanvas(t, 'offscreen', 2, 3);
+ canvas.getContext('webgpu');
+
+ // Transferring gives an ImageBitmap of the correct size filled with transparent black.
+ const ib = canvas.transferToImageBitmap();
+ t.expect(ib.width === canvas.width);
+ t.expect(ib.height === canvas.height);
+
+ const readbackCanvas = document.createElement('canvas');
+ readbackCanvas.width = canvas.width;
+ readbackCanvas.height = canvas.height;
+ const readbackContext = readbackCanvas.getContext('2d', {
+ alpha: true,
+ });
+ if (readbackContext === null) {
+ t.skip('Cannot get a 2D canvas context');
+ return;
+ }
+
+ // Since there isn't a configuration we expect the ImageBitmap to have the default alphaMode of "opaque".
+ const expected = new Uint8ClampedArray(canvas.width * canvas.height * 4);
+ for (let i = 0; i < expected.byteLength; i += 4) {
+ expected[i + 0] = 0;
+ expected[i + 1] = 0;
+ expected[i + 2] = 0;
+ expected[i + 3] = 255;
+ }
+
+ readbackContext.drawImage(ib, 0, 0);
+ readPixelsFrom2DCanvasAndCompare(t, readbackContext, expected);
+ });
+
+g.test('transferToImageBitmap_zero_size')
+ .desc(
+ `Regression test for a crash when calling transferImageBitmap on an unconfigured. Case where the canvas is empty.`
+ )
+ .params(u => u.combine('configure', [true, false]))
+ .fn(t => {
+ const { configure } = t.params;
+ const canvas = createCanvas(t, 'offscreen', 0, 1);
+ const ctx = canvas.getContext('webgpu');
+
+ if (configure) {
+ t.expectValidationError(() => ctx.configure({ device: t.device, format: 'bgra8unorm' }));
+ }
+
+ // Transferring would give an empty ImageBitmap which is not possible, so an Exception is thrown.
+ t.shouldThrow(true, () => {
+ canvas.transferToImageBitmap();
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/ImageBitmap.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/ImageBitmap.spec.js
new file mode 100644
index 0000000000..da2e7d7b31
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/ImageBitmap.spec.js
@@ -0,0 +1,558 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyExternalImageToTexture from ImageBitmaps created from various sources.
+
+TODO: Test ImageBitmap generated from all possible ImageBitmapSource, relevant ImageBitmapOptions
+ (https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#images-2)
+ and various source filetypes and metadata (weird dimensions, EXIF orientations, video rotations
+ and visible/crop rectangles, etc. (In theory these things are handled inside createImageBitmap,
+ but in theory could affect the internal representation of the ImageBitmap.)
+
+TODO: Test zero-sized copies from all sources (just make sure params cover it) (e.g. 0x0, 0x4, 4x0).
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { kTextureFormatInfo, kValidTextureFormatsForCopyE2T } from '../../capability_info.js';
+import { CopyToTextureUtils, kCopySubrectInfo } from '../../util/copy_to_texture.js';
+
+import { TexelView } from '../../util/texture/texel_view.js';
+
+// None of the dst texture format is 'uint' or 'sint', so we can always use float value.
+const kColors = {
+ Red: { R: 1.0, G: 0.0, B: 0.0, A: 1.0 },
+ Green: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ Blue: { R: 0.0, G: 0.0, B: 1.0, A: 1.0 },
+ Black: { R: 0.0, G: 0.0, B: 0.0, A: 1.0 },
+ White: { R: 1.0, G: 1.0, B: 1.0, A: 1.0 },
+ SemitransparentWhite: { R: 1.0, G: 1.0, B: 1.0, A: 0.6 },
+};
+const kTestColorsOpaque = [kColors.Red, kColors.Green, kColors.Blue, kColors.Black, kColors.White];
+
+const kTestColorsAll = [...kTestColorsOpaque, kColors.SemitransparentWhite];
+
+function makeTestColorsTexelView({ testColors, format, width, height, premultiplied, flipY }) {
+ return TexelView.fromTexelsAsColors(format, coords => {
+ const y = flipY ? height - coords.y - 1 : coords.y;
+ const pixelPos = y * width + coords.x;
+ const currentPixel = testColors[pixelPos % testColors.length];
+
+ if (premultiplied && currentPixel.A !== 1.0) {
+ return {
+ R: currentPixel.R * currentPixel.A,
+ G: currentPixel.G * currentPixel.A,
+ B: currentPixel.B * currentPixel.A,
+ A: currentPixel.A,
+ };
+ } else {
+ return currentPixel;
+ }
+ });
+}
+
+export const g = makeTestGroup(CopyToTextureUtils);
+
+g.test('from_ImageData')
+ .desc(
+ `
+ Test ImageBitmap generated from ImageData can be copied to WebGPU
+ texture correctly. These imageBitmaps are highly possible living
+ in CPU back resource.
+
+ It generates pixels in ImageData one by one based on a color list:
+ [Red, Green, Blue, Black, White, SemitransparentWhite].
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the ImageBitmap contents.
+
+ Do premultiply alpha during copy if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and do unpremultiply alpha if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ The tests covers:
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('alpha', ['none', 'premultiply'])
+ .combine('orientation', ['none', 'flipY'])
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ .combine('dstPremultiplied', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15, 255, 256])
+ .combine('height', [1, 2, 4, 15, 255, 256])
+ )
+ .fn(async t => {
+ const {
+ width,
+ height,
+ alpha,
+ orientation,
+ dstColorFormat,
+ dstPremultiplied,
+ srcDoFlipYDuringCopy,
+ } = t.params;
+
+ const testColors = kTestColorsAll;
+
+ // Generate correct expected values
+ const texelViewSource = makeTestColorsTexelView({
+ testColors,
+ format: 'rgba8unorm', // ImageData is always in rgba8unorm format.
+ width,
+ height,
+ flipY: false,
+ premultiplied: false,
+ });
+ const imageData = new ImageData(width, height);
+ texelViewSource.writeTextureData(imageData.data, {
+ bytesPerRow: width * 4,
+ rowsPerImage: height,
+ subrectOrigin: [0, 0],
+ subrectSize: { width, height },
+ });
+
+ const imageBitmap = await createImageBitmap(imageData, {
+ premultiplyAlpha: alpha,
+ imageOrientation: orientation,
+ });
+
+ const dst = t.device.createTexture({
+ size: { width, height },
+ format: dstColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const expFormat = kTextureFormatInfo[dstColorFormat].baseFormat ?? dstColorFormat;
+ const flipSrcBeforeCopy = orientation === 'flipY';
+ const texelViewExpected = t.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: imageData.data,
+ srcOrigin: [0, 0],
+ srcSize: [width, height],
+ dstOrigin: [0, 0],
+ dstSize: [width, height],
+ subRectSize: [width, height],
+ format: expFormat,
+ flipSrcBeforeCopy,
+ srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: false,
+ dstPremultiplied,
+ },
+ });
+
+ t.doTestAndCheckResult(
+ { source: imageBitmap, origin: { x: 0, y: 0 }, flipY: srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: { x: 0, y: 0 },
+ colorSpace: 'srgb',
+ premultipliedAlpha: dstPremultiplied,
+ },
+ texelViewExpected,
+ { width, height, depthOrArrayLayers: 1 },
+ // 1.0 and 0.6 are representable precisely by all formats except rgb10a2unorm, but
+ // allow diffs of 1ULP since that's the generally-appropriate threshold.
+ { maxDiffULPsForFloatFormat: 1, maxDiffULPsForNormFormat: 1 }
+ );
+ });
+
+g.test('from_canvas')
+ .desc(
+ `
+ Test ImageBitmap generated from canvas/offscreenCanvas can be copied to WebGPU
+ texture correctly. These imageBitmaps are highly possible living in GPU back resource.
+
+ It generates pixels in ImageData one by one based on a color list:
+ [Red, Green, Blue, Black, White].
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the ImageBitmap contents.
+
+ Do premultiply alpha during copy if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and do unpremultiply alpha if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ The tests covers:
+ - Valid 2D canvas
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('orientation', ['none', 'flipY'])
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ .combine('dstPremultiplied', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15, 255, 256])
+ .combine('height', [1, 2, 4, 15, 255, 256])
+ )
+ .fn(async t => {
+ const {
+ width,
+ height,
+ orientation,
+ dstColorFormat,
+ dstPremultiplied,
+ srcDoFlipYDuringCopy,
+ } = t.params;
+
+ // CTS sometimes runs on worker threads, where document is not available.
+ // In this case, OffscreenCanvas can be used instead of <canvas>.
+ // But some browsers don't support OffscreenCanvas, and some don't
+ // support '2d' contexts on OffscreenCanvas.
+ // In this situation, the case will be skipped.
+ let imageCanvas;
+ if (typeof document !== 'undefined') {
+ imageCanvas = document.createElement('canvas');
+ imageCanvas.width = width;
+ imageCanvas.height = height;
+ } else if (typeof OffscreenCanvas === 'undefined') {
+ t.skip('OffscreenCanvas is not supported');
+ return;
+ } else {
+ imageCanvas = new OffscreenCanvas(width, height);
+ }
+ const imageCanvasContext = imageCanvas.getContext('2d');
+ if (imageCanvasContext === null) {
+ t.skip('OffscreenCanvas "2d" context not available');
+ return;
+ }
+
+ // Generate non-transparent pixel data to avoid canvas
+ // different opt behaviour on putImageData()
+ // from browsers.
+ const texelViewSource = makeTestColorsTexelView({
+ testColors: kTestColorsOpaque,
+ format: 'rgba8unorm', // ImageData is always in rgba8unorm format.
+ width,
+ height,
+ flipY: false,
+ premultiplied: false,
+ });
+ // Generate correct expected values
+ const imageData = new ImageData(width, height);
+ texelViewSource.writeTextureData(imageData.data, {
+ bytesPerRow: width * 4,
+ rowsPerImage: height,
+ subrectOrigin: [0, 0],
+ subrectSize: { width, height },
+ });
+
+ // Use putImageData to prevent color space conversion.
+ imageCanvasContext.putImageData(imageData, 0, 0);
+
+ // MAINTENANCE_TODO: Workaround for @types/offscreencanvas missing an overload of
+ // `createImageBitmap` that takes `ImageBitmapOptions`.
+ const imageBitmap = await createImageBitmap(imageCanvas, {
+ premultiplyAlpha: 'premultiply',
+ imageOrientation: orientation,
+ });
+
+ const dst = t.device.createTexture({
+ size: { width, height },
+ format: dstColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const expFormat = kTextureFormatInfo[dstColorFormat].baseFormat ?? dstColorFormat;
+ const flipSrcBeforeCopy = orientation === 'flipY';
+ const texelViewExpected = t.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: imageData.data,
+ srcOrigin: [0, 0],
+ srcSize: [width, height],
+ dstOrigin: [0, 0],
+ dstSize: [width, height],
+ subRectSize: [width, height],
+ format: expFormat,
+ flipSrcBeforeCopy,
+ srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: false,
+ dstPremultiplied,
+ },
+ });
+
+ t.doTestAndCheckResult(
+ { source: imageBitmap, origin: { x: 0, y: 0 }, flipY: srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: { x: 0, y: 0 },
+ colorSpace: 'srgb',
+ premultipliedAlpha: dstPremultiplied,
+ },
+ texelViewExpected,
+ { width, height, depthOrArrayLayers: 1 },
+ // 1.0 and 0.6 are representable precisely by all formats except rgb10a2unorm, but
+ // allow diffs of 1ULP since that's the generally-appropriate threshold.
+ { maxDiffULPsForFloatFormat: 1, maxDiffULPsForNormFormat: 1 }
+ );
+ });
+
+g.test('copy_subrect_from_ImageData')
+ .desc(
+ `
+ Test ImageBitmap generated from ImageData can be copied to WebGPU
+ texture correctly. These imageBitmaps are highly possible living in CPU back resource.
+
+ It generates pixels in ImageData one by one based on a color list:
+ [Red, Green, Blue, Black, White].
+
+ Then call copyExternalImageToTexture() to do a subrect copy, based on a predefined copy
+ rect info list, to the 0 mipLevel of dst texture, and read the contents out to compare
+ with the ImageBitmap contents.
+
+ Do premultiply alpha during copy if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and do unpremultiply alpha if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped, and origin is top-left consistantly.
+
+ The tests covers:
+ - Source WebGPU Canvas lives in the same GPUDevice or different GPUDevice as test
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+ - Valid subrect copies.
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('alpha', ['none', 'premultiply'])
+ .combine('orientation', ['none', 'flipY'])
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .combine('dstPremultiplied', [true, false])
+ .beginSubcases()
+ .combine('copySubRectInfo', kCopySubrectInfo)
+ )
+ .fn(async t => {
+ const {
+ copySubRectInfo,
+ alpha,
+ orientation,
+ dstPremultiplied,
+ srcDoFlipYDuringCopy,
+ } = t.params;
+
+ const testColors = kTestColorsAll;
+ const { srcOrigin, dstOrigin, srcSize, dstSize, copyExtent } = copySubRectInfo;
+ const kColorFormat = 'rgba8unorm';
+
+ // Generate correct expected values
+ const texelViewSource = makeTestColorsTexelView({
+ testColors,
+ format: kColorFormat, // ImageData is always in rgba8unorm format.
+ width: srcSize.width,
+ height: srcSize.height,
+ flipY: false,
+ premultiplied: false,
+ });
+ const imageData = new ImageData(srcSize.width, srcSize.height);
+ texelViewSource.writeTextureData(imageData.data, {
+ bytesPerRow: srcSize.width * 4,
+ rowsPerImage: srcSize.height,
+ subrectOrigin: [0, 0],
+ subrectSize: srcSize,
+ });
+
+ const imageBitmap = await createImageBitmap(imageData, {
+ premultiplyAlpha: alpha,
+ imageOrientation: orientation,
+ });
+
+ const dst = t.device.createTexture({
+ size: dstSize,
+ format: kColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const flipSrcBeforeCopy = orientation === 'flipY';
+ const texelViewExpected = t.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: imageData.data,
+ srcOrigin,
+ srcSize,
+ dstOrigin,
+ dstSize,
+ subRectSize: copyExtent,
+ format: kColorFormat,
+ flipSrcBeforeCopy,
+ srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: false,
+ dstPremultiplied,
+ },
+ });
+
+ t.doTestAndCheckResult(
+ { source: imageBitmap, origin: srcOrigin, flipY: srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: dstOrigin,
+ colorSpace: 'srgb',
+ premultipliedAlpha: dstPremultiplied,
+ },
+ texelViewExpected,
+ copyExtent,
+ // 1.0 and 0.6 are representable precisely by all formats except rgb10a2unorm, but
+ // allow diffs of 1ULP since that's the generally-appropriate threshold.
+ { maxDiffULPsForFloatFormat: 1, maxDiffULPsForNormFormat: 1 }
+ );
+ });
+
+g.test('copy_subrect_from_2D_Canvas')
+ .desc(
+ `
+ Test ImageBitmap generated from canvas/offscreenCanvas can be copied to WebGPU
+ texture correctly. These imageBitmaps are highly possible living in GPU back resource.
+
+ It generates pixels in ImageData one by one based on a color list:
+ [Red, Green, Blue, Black, White].
+
+ Then call copyExternalImageToTexture() to do a subrect copy, based on a predefined copy
+ rect info list, to the 0 mipLevel of dst texture, and read the contents out to compare
+ with the ImageBitmap contents.
+
+ Do premultiply alpha during copy if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and do unpremultiply alpha if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped, and origin is top-left consistantly.
+
+ The tests covers:
+ - Source WebGPU Canvas lives in the same GPUDevice or different GPUDevice as test
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+ - Valid subrect copies.
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('orientation', ['none', 'flipY'])
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .combine('dstPremultiplied', [true, false])
+ .beginSubcases()
+ .combine('copySubRectInfo', kCopySubrectInfo)
+ )
+ .fn(async t => {
+ const { copySubRectInfo, orientation, dstPremultiplied, srcDoFlipYDuringCopy } = t.params;
+
+ const { srcOrigin, dstOrigin, srcSize, dstSize, copyExtent } = copySubRectInfo;
+ const kColorFormat = 'rgba8unorm';
+
+ // CTS sometimes runs on worker threads, where document is not available.
+ // In this case, OffscreenCanvas can be used instead of <canvas>.
+ // But some browsers don't support OffscreenCanvas, and some don't
+ // support '2d' contexts on OffscreenCanvas.
+ // In this situation, the case will be skipped.
+ let imageCanvas;
+ if (typeof document !== 'undefined') {
+ imageCanvas = document.createElement('canvas');
+ imageCanvas.width = srcSize.width;
+ imageCanvas.height = srcSize.height;
+ } else if (typeof OffscreenCanvas === 'undefined') {
+ t.skip('OffscreenCanvas is not supported');
+ return;
+ } else {
+ imageCanvas = new OffscreenCanvas(srcSize.width, srcSize.height);
+ }
+ const imageCanvasContext = imageCanvas.getContext('2d');
+ if (imageCanvasContext === null) {
+ t.skip('OffscreenCanvas "2d" context not available');
+ return;
+ }
+
+ // Generate non-transparent pixel data to avoid canvas
+ // different opt behaviour on putImageData()
+ // from browsers.
+ const texelViewSource = makeTestColorsTexelView({
+ testColors: kTestColorsOpaque,
+ format: 'rgba8unorm', // ImageData is always in rgba8unorm format.
+ width: srcSize.width,
+ height: srcSize.height,
+ flipY: false,
+ premultiplied: false,
+ });
+ // Generate correct expected values
+ const imageData = new ImageData(srcSize.width, srcSize.height);
+ texelViewSource.writeTextureData(imageData.data, {
+ bytesPerRow: srcSize.width * 4,
+ rowsPerImage: srcSize.height,
+ subrectOrigin: [0, 0],
+ subrectSize: srcSize,
+ });
+
+ // Use putImageData to prevent color space conversion.
+ imageCanvasContext.putImageData(imageData, 0, 0);
+
+ // MAINTENANCE_TODO: Workaround for @types/offscreencanvas missing an overload of
+ // `createImageBitmap` that takes `ImageBitmapOptions`.
+ const imageBitmap = await createImageBitmap(imageCanvas, {
+ premultiplyAlpha: 'premultiply',
+ imageOrientation: orientation,
+ });
+
+ const dst = t.device.createTexture({
+ size: dstSize,
+ format: kColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const flipSrcBeforeCopy = orientation === 'flipY';
+ const texelViewExpected = t.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: imageData.data,
+ srcOrigin,
+ srcSize,
+ dstOrigin,
+ dstSize,
+ subRectSize: copyExtent,
+ format: kColorFormat,
+ flipSrcBeforeCopy,
+ srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: false,
+ dstPremultiplied,
+ },
+ });
+
+ t.doTestAndCheckResult(
+ { source: imageBitmap, origin: srcOrigin, flipY: srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: dstOrigin,
+ colorSpace: 'srgb',
+ premultipliedAlpha: dstPremultiplied,
+ },
+ texelViewExpected,
+ copyExtent,
+ // 1.0 and 0.6 are representable precisely by all formats except rgb10a2unorm, but
+ // allow diffs of 1ULP since that's the generally-appropriate threshold.
+ { maxDiffULPsForFloatFormat: 1, maxDiffULPsForNormFormat: 1 }
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js
new file mode 100644
index 0000000000..372f8d6827
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/canvas.spec.js
@@ -0,0 +1,679 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyToTexture with HTMLCanvasElement and OffscreenCanvas sources.
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import {
+ kCanvasAlphaModes,
+ kTextureFormatInfo,
+ kValidTextureFormatsForCopyE2T,
+} from '../../capability_info.js';
+import { CopyToTextureUtils } from '../../util/copy_to_texture.js';
+import { kAllCanvasTypes, createCanvas } from '../../util/create_elements.js';
+
+class F extends CopyToTextureUtils {
+ init2DCanvasContentWithColorSpace({ width, height, colorSpace }) {
+ const canvas = createCanvas(this, 'onscreen', width, height);
+
+ let canvasContext = null;
+ canvasContext = canvas.getContext('2d', { colorSpace });
+
+ if (canvasContext === null) {
+ this.skip('onscreen canvas 2d context not available');
+ }
+
+ if (
+ typeof canvasContext.getContextAttributes === 'undefined' ||
+ typeof canvasContext.getContextAttributes().colorSpace === 'undefined'
+ ) {
+ this.skip('color space attr is not supported for canvas 2d context');
+ }
+
+ const SOURCE_PIXEL_BYTES = 4;
+ const imagePixels = new Uint8ClampedArray(SOURCE_PIXEL_BYTES * width * height);
+
+ const rectWidth = Math.floor(width / 2);
+ const rectHeight = Math.floor(height / 2);
+
+ const alphaValue = 153;
+
+ let pixelStartPos = 0;
+ // Red;
+ for (let i = 0; i < rectHeight; ++i) {
+ for (let j = 0; j < rectWidth; ++j) {
+ pixelStartPos = (i * width + j) * SOURCE_PIXEL_BYTES;
+ imagePixels[pixelStartPos] = 255;
+ imagePixels[pixelStartPos + 1] = 0;
+ imagePixels[pixelStartPos + 2] = 0;
+ imagePixels[pixelStartPos + 3] = alphaValue;
+ }
+ }
+
+ // Lime;
+ for (let i = 0; i < rectHeight; ++i) {
+ for (let j = rectWidth; j < width; ++j) {
+ pixelStartPos = (i * width + j) * SOURCE_PIXEL_BYTES;
+ imagePixels[pixelStartPos] = 0;
+ imagePixels[pixelStartPos + 1] = 255;
+ imagePixels[pixelStartPos + 2] = 0;
+ imagePixels[pixelStartPos + 3] = alphaValue;
+ }
+ }
+
+ // Blue
+ for (let i = rectHeight; i < height; ++i) {
+ for (let j = 0; j < rectWidth; ++j) {
+ pixelStartPos = (i * width + j) * SOURCE_PIXEL_BYTES;
+ imagePixels[pixelStartPos] = 0;
+ imagePixels[pixelStartPos + 1] = 0;
+ imagePixels[pixelStartPos + 2] = 255;
+ imagePixels[pixelStartPos + 3] = alphaValue;
+ }
+ }
+
+ // Fuchsia
+ for (let i = rectHeight; i < height; ++i) {
+ for (let j = rectWidth; j < width; ++j) {
+ pixelStartPos = (i * width + j) * SOURCE_PIXEL_BYTES;
+ imagePixels[pixelStartPos] = 255;
+ imagePixels[pixelStartPos + 1] = 0;
+ imagePixels[pixelStartPos + 2] = 255;
+ imagePixels[pixelStartPos + 3] = alphaValue;
+ }
+ }
+
+ const imageData = new ImageData(imagePixels, width, height, { colorSpace });
+ // MAINTENANCE_TODO: Remove as any when tsc support imageData.colorSpace
+
+ if (typeof imageData.colorSpace === 'undefined') {
+ this.skip('color space attr is not supported for ImageData');
+ }
+
+ const ctx = canvasContext;
+ ctx.putImageData(imageData, 0, 0);
+
+ return {
+ canvas,
+ expectedSourceData: this.getExpectedReadbackFor2DCanvas(canvasContext, width, height),
+ };
+ }
+
+ // MAINTENANCE_TODO: Cache the generated canvas to avoid duplicated initialization.
+ init2DCanvasContent({ canvasType, width, height }) {
+ const canvas = createCanvas(this, canvasType, width, height);
+
+ let canvasContext = null;
+ canvasContext = canvas.getContext('2d');
+
+ if (canvasContext === null) {
+ this.skip(canvasType + ' canvas 2d context not available');
+ }
+
+ const ctx = canvasContext;
+ this.paint2DCanvas(ctx, width, height, 0.6);
+
+ return {
+ canvas,
+ expectedSourceData: this.getExpectedReadbackFor2DCanvas(canvasContext, width, height),
+ };
+ }
+
+ paint2DCanvas(ctx, width, height, alphaValue) {
+ const rectWidth = Math.floor(width / 2);
+ const rectHeight = Math.floor(height / 2);
+
+ // Red
+ ctx.fillStyle = `rgba(255, 0, 0, ${alphaValue})`;
+ ctx.fillRect(0, 0, rectWidth, rectHeight);
+ // Lime
+ ctx.fillStyle = `rgba(0, 255, 0, ${alphaValue})`;
+ ctx.fillRect(rectWidth, 0, width - rectWidth, rectHeight);
+ // Blue
+ ctx.fillStyle = `rgba(0, 0, 255, ${alphaValue})`;
+ ctx.fillRect(0, rectHeight, rectWidth, height - rectHeight);
+ // Fuchsia
+ ctx.fillStyle = `rgba(255, 0, 255, ${alphaValue})`;
+ ctx.fillRect(rectWidth, rectHeight, width - rectWidth, height - rectHeight);
+ }
+
+ // MAINTENANCE_TODO: Cache the generated canvas to avoid duplicated initialization.
+ initGLCanvasContent({ canvasType, contextName, width, height, premultiplied }) {
+ const canvas = createCanvas(this, canvasType, width, height);
+
+ // MAINTENANCE_TODO: Workaround for @types/offscreencanvas missing an overload of
+ // `OffscreenCanvas.getContext` that takes `string` or a union of context types.
+ const gl = canvas.getContext(contextName, {
+ premultipliedAlpha: premultiplied,
+ });
+
+ if (gl === null) {
+ this.skip(canvasType + ' canvas ' + contextName + ' context not available');
+ }
+ this.trackForCleanup(gl);
+
+ const rectWidth = Math.floor(width / 2);
+ const rectHeight = Math.floor(height / 2);
+
+ const alphaValue = 0.6;
+ const colorValue = premultiplied ? alphaValue : 1.0;
+
+ // For webgl/webgl2 context canvas, if the context created with premultipliedAlpha attributes,
+ // it means that the value in drawing buffer is premultiplied or not. So we should set
+ // premultipliedAlpha value for premultipliedAlpha true gl context and unpremultipliedAlpha value
+ // for the premultipliedAlpha false gl context.
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0, 0, rectWidth, rectHeight);
+ gl.clearColor(colorValue, 0.0, 0.0, alphaValue);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(rectWidth, 0, width - rectWidth, rectHeight);
+ gl.clearColor(0.0, colorValue, 0.0, alphaValue);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(0, rectHeight, rectWidth, height - rectHeight);
+ gl.clearColor(0.0, 0.0, colorValue, alphaValue);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(rectWidth, rectHeight, width - rectWidth, height - rectHeight);
+ gl.clearColor(colorValue, colorValue, colorValue, alphaValue);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ return {
+ canvas,
+ expectedSourceData: this.getExpectedReadbackForWebGLCanvas(gl, width, height),
+ };
+ }
+
+ getDataToInitSourceWebGPUCanvas(width, height, alphaMode) {
+ const rectWidth = Math.floor(width / 2);
+ const rectHeight = Math.floor(height / 2);
+
+ const alphaValue = 153;
+ // Always output [153, 153, 153, 153]. When the alphaMode is...
+ // - premultiplied: the readback is CSS `rgba(255, 255, 255, 60%)`.
+ // - opaque: the readback is CSS `rgba(153, 153, 153, 100%)`.
+ // getExpectedReadbackForWebGPUCanvas matches this.
+ const colorValue = alphaValue;
+
+ // BGRA8Unorm texture
+ const initialData = new Uint8ClampedArray(4 * width * height);
+ const maxRectHeightIndex = width * rectHeight;
+ for (let pixelIndex = 0; pixelIndex < initialData.length / 4; ++pixelIndex) {
+ const index = pixelIndex * 4;
+
+ // Top-half two rectangles
+ if (pixelIndex < maxRectHeightIndex) {
+ // top-left side rectangle
+ if (pixelIndex % width < rectWidth) {
+ // top-left side rectangle
+ initialData[index] = colorValue;
+ initialData[index + 1] = 0;
+ initialData[index + 2] = 0;
+ initialData[index + 3] = alphaValue;
+ } else {
+ // top-right side rectangle
+ initialData[index] = 0;
+ initialData[index + 1] = colorValue;
+ initialData[index + 2] = 0;
+ initialData[index + 3] = alphaValue;
+ }
+ } else {
+ // Bottom-half two rectangles
+ // bottom-left side rectangle
+ if (pixelIndex % width < rectWidth) {
+ initialData[index] = 0;
+ initialData[index + 1] = 0;
+ initialData[index + 2] = colorValue;
+ initialData[index + 3] = alphaValue;
+ } else {
+ // bottom-right side rectangle
+ initialData[index] = colorValue;
+ initialData[index + 1] = colorValue;
+ initialData[index + 2] = colorValue;
+ initialData[index + 3] = alphaValue;
+ }
+ }
+ }
+ return initialData;
+ }
+
+ initSourceWebGPUCanvas({ device, canvasType, width, height, alphaMode }) {
+ const canvas = createCanvas(this, canvasType, width, height);
+
+ const gpuContext = canvas.getContext('webgpu');
+
+ if (!(gpuContext instanceof GPUCanvasContext)) {
+ this.skip(canvasType + ' canvas webgpu context not available');
+ }
+
+ gpuContext.configure({
+ device,
+ format: 'bgra8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ alphaMode,
+ });
+
+ // BGRA8Unorm texture
+ const initialData = this.getDataToInitSourceWebGPUCanvas(width, height, alphaMode);
+ const canvasTexture = gpuContext.getCurrentTexture();
+ device.queue.writeTexture(
+ { texture: canvasTexture },
+ initialData,
+ {
+ bytesPerRow: width * 4,
+ rowsPerImage: height,
+ },
+ {
+ width,
+ height,
+ depthOrArrayLayers: 1,
+ }
+ );
+
+ return {
+ canvas,
+ expectedSourceData: this.getExpectedReadbackForWebGPUCanvas(width, height, alphaMode),
+ };
+ }
+
+ getExpectedReadbackFor2DCanvas(context, width, height) {
+ // Always read back the raw data from canvas
+ return context.getImageData(0, 0, width, height).data;
+ }
+
+ getExpectedReadbackForWebGLCanvas(gl, width, height) {
+ const bytesPerPixel = 4;
+
+ const sourcePixels = new Uint8ClampedArray(width * height * bytesPerPixel);
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, sourcePixels);
+
+ return this.doFlipY(sourcePixels, width, height, bytesPerPixel);
+ }
+
+ getExpectedReadbackForWebGPUCanvas(width, height, alphaMode) {
+ const bytesPerPixel = 4;
+
+ const rgbaPixels = this.getDataToInitSourceWebGPUCanvas(width, height, alphaMode);
+
+ // The source canvas has bgra8unorm back resource. We
+ // swizzle the channels to align with 2d/webgl canvas and
+ // clear alpha to 255 (1.0) when context alphaMode
+ // is set to opaque (follow webgpu spec).
+ for (let i = 0; i < height; ++i) {
+ for (let j = 0; j < width; ++j) {
+ const pixelPos = i * width + j;
+ const r = rgbaPixels[pixelPos * bytesPerPixel + 2];
+ if (alphaMode === 'opaque') {
+ rgbaPixels[pixelPos * bytesPerPixel + 3] = 255;
+ }
+
+ rgbaPixels[pixelPos * bytesPerPixel + 2] = rgbaPixels[pixelPos * bytesPerPixel];
+ rgbaPixels[pixelPos * bytesPerPixel] = r;
+ }
+ }
+
+ return rgbaPixels;
+ }
+
+ doCopyContentsTest(source, expectedSourceImage, p) {
+ const dst = this.device.createTexture({
+ size: {
+ width: p.width,
+ height: p.height,
+ depthOrArrayLayers: 1,
+ },
+ format: p.dstColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ // Construct expected value for different dst color format
+ const info = kTextureFormatInfo[p.dstColorFormat];
+ const expFormat = info.baseFormat ?? p.dstColorFormat;
+
+ // For 2d canvas, get expected pixels with getImageData(), which returns unpremultiplied
+ // values.
+ const expectedDestinationImage = this.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: expectedSourceImage,
+ srcOrigin: [0, 0],
+ srcSize: [p.width, p.height],
+ dstOrigin: [0, 0],
+ dstSize: [p.width, p.height],
+ subRectSize: [p.width, p.height],
+ format: expFormat,
+ flipSrcBeforeCopy: false,
+ srcDoFlipYDuringCopy: p.srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: p.srcPremultiplied,
+ dstPremultiplied: p.dstPremultiplied,
+ },
+ });
+
+ this.doTestAndCheckResult(
+ { source, origin: { x: 0, y: 0 }, flipY: p.srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: { x: 0, y: 0 },
+ colorSpace: 'srgb',
+ premultipliedAlpha: p.dstPremultiplied,
+ },
+ expectedDestinationImage,
+ { width: p.width, height: p.height, depthOrArrayLayers: 1 },
+ // 1.0 and 0.6 are representable precisely by all formats except rgb10a2unorm, but
+ // allow diffs of 1ULP since that's the generally-appropriate threshold.
+ { maxDiffULPsForNormFormat: 1, maxDiffULPsForFloatFormat: 1 }
+ );
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('copy_contents_from_2d_context_canvas')
+ .desc(
+ `
+ Test HTMLCanvasElement and OffscreenCanvas with 2d context
+ can be copied to WebGPU texture correctly.
+
+ It creates HTMLCanvasElement/OffscreenCanvas with '2d'.
+ Use fillRect(2d context) to render red rect for top-left,
+ green rect for top-right, blue rect for bottom-left and white for bottom-right.
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the canvas contents.
+
+ Provide premultiplied input if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and unpremultiplied input if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ The tests covers:
+ - Valid canvas type
+ - Valid 2d context type
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+ - TODO(#913): color space tests need to be added
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ .combine('dstAlphaMode', kCanvasAlphaModes)
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15])
+ .combine('height', [1, 2, 4, 15])
+ )
+ .fn(async t => {
+ const { width, height, canvasType, dstAlphaMode } = t.params;
+
+ const { canvas, expectedSourceData } = t.init2DCanvasContent({
+ canvasType,
+ width,
+ height,
+ });
+
+ t.doCopyContentsTest(canvas, expectedSourceData, {
+ srcPremultiplied: false,
+ dstPremultiplied: dstAlphaMode === 'premultiplied',
+ ...t.params,
+ });
+ });
+
+g.test('copy_contents_from_gl_context_canvas')
+ .desc(
+ `
+ Test HTMLCanvasElement and OffscreenCanvas with webgl/webgl2 context
+ can be copied to WebGPU texture correctly.
+
+ It creates HTMLCanvasElement/OffscreenCanvas with webgl'/'webgl2'.
+ Use scissor + clear to render red rect for top-left, green rect
+ for top-right, blue rect for bottom-left and white for bottom-right.
+ And do premultiply alpha in advance if the webgl/webgl2 context is created
+ with premultipliedAlpha : true.
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the canvas contents.
+
+ Provide premultiplied input if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and unpremultiplied input if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ The tests covers:
+ - Valid canvas type
+ - Valid webgl/webgl2 context type
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage'(named 'srcDoFlipYDuringCopy' in cases)
+ - TODO: color space tests need to be added
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('contextName', ['webgl', 'webgl2'])
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ .combine('srcPremultiplied', [true, false])
+ .combine('dstAlphaMode', kCanvasAlphaModes)
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15])
+ .combine('height', [1, 2, 4, 15])
+ )
+ .fn(async t => {
+ const { width, height, canvasType, contextName, srcPremultiplied, dstAlphaMode } = t.params;
+
+ const { canvas, expectedSourceData } = t.initGLCanvasContent({
+ canvasType,
+ contextName,
+ width,
+ height,
+ premultiplied: srcPremultiplied,
+ });
+
+ t.doCopyContentsTest(canvas, expectedSourceData, {
+ dstPremultiplied: dstAlphaMode === 'premultiplied',
+ ...t.params,
+ });
+ });
+
+g.test('copy_contents_from_gpu_context_canvas')
+ .desc(
+ `
+ Test HTMLCanvasElement and OffscreenCanvas with webgpu context
+ can be copied to WebGPU texture correctly.
+
+ It creates HTMLCanvasElement/OffscreenCanvas with 'webgpu'.
+ Use writeTexture to copy pixels to back buffer. The results are:
+ red rect for top-left, green rect for top-right, blue rect for bottom-left
+ and white for bottom-right.
+
+ TODO: Actually test alphaMode = opaque.
+ And do premultiply alpha in advance if the webgpu context is created
+ with alphaMode="premultiplied".
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the canvas contents.
+
+ Provide premultiplied input if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and unpremultiplied input if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ The tests covers:
+ - Valid canvas type
+ - Source WebGPU Canvas lives in the same GPUDevice or different GPUDevice as test
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - TODO: test more source image alphaMode
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage'(named 'srcDoFlipYDuringCopy' in cases)
+ - TODO: color space tests need to be added
+
+ And the expected results are all passed.
+ `
+ )
+ .params(u =>
+ u
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('srcAndDstInSameGPUDevice', [true, false])
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ // .combine('srcAlphaMode', kCanvasAlphaModes)
+ .combine('srcAlphaMode', ['premultiplied'])
+ .combine('dstAlphaMode', kCanvasAlphaModes)
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15])
+ .combine('height', [1, 2, 4, 15])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const {
+ width,
+ height,
+ canvasType,
+ srcAndDstInSameGPUDevice,
+ srcAlphaMode,
+ dstAlphaMode,
+ } = t.params;
+
+ const device = srcAndDstInSameGPUDevice ? t.device : t.mismatchedDevice;
+ const { canvas: source, expectedSourceData } = t.initSourceWebGPUCanvas({
+ device,
+ canvasType,
+ width,
+ height,
+ alphaMode: srcAlphaMode,
+ });
+
+ t.doCopyContentsTest(source, expectedSourceData, {
+ srcPremultiplied: srcAlphaMode === 'premultiplied',
+ dstPremultiplied: dstAlphaMode === 'premultiplied',
+ ...t.params,
+ });
+ });
+
+g.test('color_space_conversion')
+ .desc(
+ `
+ Test HTMLCanvasElement with 2d context can created with 'colorSpace' attribute.
+ Using CopyExternalImageToTexture to copy from such type of canvas needs
+ to do color space converting correctly.
+
+ It creates HTMLCanvasElement/OffscreenCanvas with '2d' and 'colorSpace' attributes.
+ Use fillRect(2d context) to render red rect for top-left,
+ green rect for top-right, blue rect for bottom-left and white for bottom-right.
+
+ Then call copyExternalImageToTexture() to do a full copy to the 0 mipLevel
+ of dst texture, and read the contents out to compare with the canvas contents.
+
+ Provide premultiplied input if 'premultipliedAlpha' in 'GPUImageCopyTextureTagged'
+ is set to 'true' and unpremultiplied input if it is set to 'false'.
+
+ If 'flipY' in 'GPUImageCopyExternalImage' is set to 'true', copy will ensure the result
+ is flipped.
+
+ If color space from source input and user defined dstTexture color space are different, the
+ result must convert the content to user defined color space
+
+ The tests covers:
+ - Valid dstColorFormat of copyExternalImageToTexture()
+ - Valid dest alphaMode
+ - Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
+ - Valid 'colorSpace' config in 'dstColorSpace'
+
+ And the expected results are all passed.
+
+ TODO: Enhance test data with colors that aren't always opaque and fully saturated.
+ TODO: Consider refactoring src data setup with TexelView.writeTextureData.
+ `
+ )
+ .params(u =>
+ u
+ .combine('srcColorSpace', ['srgb', 'display-p3'])
+ .combine('dstColorSpace', ['srgb'])
+ .combine('dstColorFormat', kValidTextureFormatsForCopyE2T)
+ .combine('dstPremultiplied', [true, false])
+ .combine('srcDoFlipYDuringCopy', [true, false])
+ .beginSubcases()
+ .combine('width', [1, 2, 4, 15, 255, 256])
+ .combine('height', [1, 2, 4, 15, 255, 256])
+ )
+ .fn(async t => {
+ const {
+ width,
+ height,
+ srcColorSpace,
+ dstColorSpace,
+ dstColorFormat,
+ dstPremultiplied,
+ srcDoFlipYDuringCopy,
+ } = t.params;
+ const { canvas, expectedSourceData } = t.init2DCanvasContentWithColorSpace({
+ width,
+ height,
+ colorSpace: srcColorSpace,
+ });
+
+ const dst = t.device.createTexture({
+ size: { width, height },
+ format: dstColorFormat,
+ usage:
+ GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const expectedDestinationImage = t.getExpectedDstPixelsFromSrcPixels({
+ srcPixels: expectedSourceData,
+ srcOrigin: [0, 0],
+ srcSize: [width, height],
+ dstOrigin: [0, 0],
+ dstSize: [width, height],
+ subRectSize: [width, height],
+ // copyExternalImageToTexture does not perform gamma-encoding into `-srgb` formats.
+ format: kTextureFormatInfo[dstColorFormat].baseFormat ?? dstColorFormat,
+ flipSrcBeforeCopy: false,
+ srcDoFlipYDuringCopy,
+ conversion: {
+ srcPremultiplied: false,
+ dstPremultiplied,
+ srcColorSpace,
+ dstColorSpace,
+ },
+ });
+
+ const texelCompareOptions = {
+ maxFractionalDiff: 0,
+ maxDiffULPsForNormFormat: 1,
+ };
+ if (srcColorSpace !== dstColorSpace) {
+ // Color space conversion seems prone to errors up to about 0.0003 on f32, 0.0007 on f16.
+ texelCompareOptions.maxFractionalDiff = 0.001;
+ } else {
+ texelCompareOptions.maxDiffULPsForFloatFormat = 1;
+ }
+
+ t.doTestAndCheckResult(
+ { source: canvas, origin: { x: 0, y: 0 }, flipY: srcDoFlipYDuringCopy },
+ {
+ texture: dst,
+ origin: { x: 0, y: 0 },
+ colorSpace: dstColorSpace,
+ premultipliedAlpha: dstPremultiplied,
+ },
+ expectedDestinationImage,
+ { width, height, depthOrArrayLayers: 1 },
+ texelCompareOptions
+ );
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js
new file mode 100644
index 0000000000..688f90cd4a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/copyToTexture/video.spec.js
@@ -0,0 +1,16 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+copyToTexture with HTMLVideoElement (and other video-type sources?).
+
+- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), color spaces
+ (bt.601, bt.709, bt.2020)
+- TODO: enhance with more cases with crop, rotation, etc.
+
+TODO: consider whether external_texture and copyToTexture video tests should be in the same file
+TODO: plan
+`;
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js
new file mode 100644
index 0000000000..2ce0a6b2a0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/external_texture/video.spec.js
@@ -0,0 +1,426 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests for external textures from HTMLVideoElement (and other video-type sources?).
+
+- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), color spaces
+ (bt.601, bt.709, bt.2020)
+- TODO: enhance with more cases with crop, rotation, etc.
+
+TODO: consider whether external_texture and copyToTexture video tests should be in the same file
+`;
+import { getResourcePath } from '../../../common/framework/resources.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { makeTable } from '../../../common/util/data_tables.js';
+import { GPUTest } from '../../gpu_test.js';
+import {
+ startPlayingAndWaitForVideo,
+ getVideoColorSpaceInit,
+ getVideoFrameFromVideoElement,
+ waitForNextFrame,
+} from '../../web_platform/util.js';
+
+const kHeight = 16;
+const kWidth = 16;
+const kFormat = 'rgba8unorm';
+
+const kVideoInfo = makeTable(['colorSpace', 'mimeType'], [undefined, undefined], {
+ // All video names
+ 'red-green.webmvp8.webm': ['REC601', 'video/webm; codecs=vp8'],
+ 'red-green.theora.ogv': ['REC601', 'video/ogg; codecs=theora'],
+ 'red-green.mp4': ['REC601', 'video/mp4; codecs=avc1.4d400c'],
+ 'red-green.bt601.vp9.webm': ['REC601', 'video/webm; codecs=vp9'],
+ 'red-green.bt709.vp9.webm': ['REC709', 'video/webm; codecs=vp9'],
+ 'red-green.bt2020.vp9.webm': ['REC2020', 'video/webm; codecs=vp9'],
+});
+
+const kVideoExpectations = [
+ {
+ videoName: 'red-green.webmvp8.webm',
+ _redExpectation: new Uint8Array([0xf8, 0x24, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x3f, 0xfb, 0x00, 0xff]),
+ },
+ {
+ videoName: 'red-green.theora.ogv',
+ _redExpectation: new Uint8Array([0xf8, 0x24, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x3f, 0xfb, 0x00, 0xff]),
+ },
+ {
+ videoName: 'red-green.mp4',
+ _redExpectation: new Uint8Array([0xf8, 0x24, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x3f, 0xfb, 0x00, 0xff]),
+ },
+ {
+ videoName: 'red-green.bt601.vp9.webm',
+ _redExpectation: new Uint8Array([0xf8, 0x24, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x3f, 0xfb, 0x00, 0xff]),
+ },
+ {
+ videoName: 'red-green.bt709.vp9.webm',
+ _redExpectation: new Uint8Array([0xff, 0x00, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x00, 0xff, 0x00, 0xff]),
+ },
+ {
+ videoName: 'red-green.bt2020.vp9.webm',
+ _redExpectation: new Uint8Array([0xff, 0x00, 0x00, 0xff]),
+ _greenExpectation: new Uint8Array([0x00, 0xff, 0x00, 0xff]),
+ },
+];
+
+export const g = makeTestGroup(GPUTest);
+
+function createExternalTextureSamplingTestPipeline(t) {
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec4<f32>, 6>(
+ vec4<f32>( 1.0, 1.0, 0.0, 1.0),
+ vec4<f32>( 1.0, -1.0, 0.0, 1.0),
+ vec4<f32>(-1.0, -1.0, 0.0, 1.0),
+ vec4<f32>( 1.0, 1.0, 0.0, 1.0),
+ vec4<f32>(-1.0, -1.0, 0.0, 1.0),
+ vec4<f32>(-1.0, 1.0, 0.0, 1.0)
+ );
+ return pos[VertexIndex];
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var s : sampler;
+ @group(0) @binding(1) var t : texture_external;
+
+ @fragment fn main(@builtin(position) FragCoord : vec4<f32>)
+ -> @location(0) vec4<f32> {
+ return textureSampleBaseClampToEdge(t, s, FragCoord.xy / vec2<f32>(16.0, 16.0));
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [
+ {
+ format: kFormat,
+ },
+ ],
+ },
+ primitive: { topology: 'triangle-list' },
+ });
+
+ return pipeline;
+}
+
+function createExternalTextureSamplingTestBindGroup(t, source, pipeline) {
+ const linearSampler = t.device.createSampler();
+
+ const externalTexture = t.device.importExternalTexture({
+ source: source,
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: linearSampler,
+ },
+ {
+ binding: 1,
+ resource: externalTexture,
+ },
+ ],
+ });
+
+ return bindGroup;
+}
+
+function getVideoElementAndInfo(t, sourceType, videoName) {
+ if (sourceType === 'VideoFrame' && typeof VideoFrame === 'undefined') {
+ t.skip('WebCodec is not supported');
+ }
+
+ const videoElement = document.createElement('video');
+ const videoInfo = kVideoInfo[videoName];
+
+ if (videoElement.canPlayType(videoInfo.mimeType) === '') {
+ t.skip('Video codec is not supported');
+ }
+
+ const videoUrl = getResourcePath(videoName);
+ videoElement.src = videoUrl;
+
+ return { videoElement, videoInfo };
+}
+
+g.test('importExternalTexture,sample')
+ .desc(
+ `
+Tests that we can import an HTMLVideoElement/VideoFrame into a GPUExternalTexture, sample from it
+for several combinations of video format and color space.
+`
+ )
+ .params(u =>
+ u //
+ .combine('sourceType', ['VideoElement', 'VideoFrame'])
+ .combineWithParams(kVideoExpectations)
+ )
+ .fn(async t => {
+ const sourceType = t.params.sourceType;
+ const { videoElement, videoInfo } = getVideoElementAndInfo(t, sourceType, t.params.videoName);
+
+ await startPlayingAndWaitForVideo(videoElement, async () => {
+ const source =
+ sourceType === 'VideoFrame'
+ ? await getVideoFrameFromVideoElement(
+ t,
+ videoElement,
+ getVideoColorSpaceInit(videoInfo.colorSpace)
+ )
+ : videoElement;
+
+ const colorAttachment = t.device.createTexture({
+ format: kFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const pipeline = createExternalTextureSamplingTestPipeline(t);
+ const bindGroup = createExternalTextureSamplingTestBindGroup(t, source, pipeline);
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, bindGroup);
+ passEncoder.draw(6);
+ passEncoder.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+
+ // Top left corner should be red. Sample a few pixels away from the edges to avoid compression
+ // artifacts.
+ t.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ kFormat,
+ { x: 5, y: 5 },
+ {
+ exp: t.params._redExpectation,
+ }
+ );
+
+ // Bottom right corner should be green. Sample a few pixels away from the edges to avoid
+ // compression artifacts.
+ t.expectSinglePixelIn2DTexture(
+ colorAttachment,
+ kFormat,
+ { x: kWidth - 5, y: kHeight - 5 },
+ {
+ exp: t.params._greenExpectation,
+ }
+ );
+
+ if (sourceType === 'VideoFrame') source.close();
+ });
+ });
+
+g.test('importExternalTexture,expired')
+ .desc(
+ `
+Tests that GPUExternalTexture.expired is false when HTMLVideoElement is not updated
+or VideoFrame(webcodec) is alive. And it will be changed to true when imported
+HTMLVideoElement is updated or imported VideoFrame is closed. Using expired
+GPUExternalTexture results in an error.
+
+TODO: Make this test work without requestVideoFrameCallback support (in waitForNextFrame).
+`
+ )
+ .params(u =>
+ u //
+ .combine('sourceType', ['VideoElement', 'VideoFrame'])
+ )
+ .fn(async t => {
+ const sourceType = t.params.sourceType;
+ const { videoElement } = getVideoElementAndInfo(t, sourceType, 'red-green.webmvp8.webm');
+
+ if (!('requestVideoFrameCallback' in videoElement)) {
+ t.skip('HTMLVideoElement.requestVideoFrameCallback is not supported');
+ }
+
+ const colorAttachment = t.device.createTexture({
+ format: kFormat,
+ size: { width: kWidth, height: kHeight, depthOrArrayLayers: 1 },
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+ const passDescriptor = {
+ colorAttachments: [
+ {
+ view: colorAttachment.createView(),
+ clearValue: [0, 0, 0, 1],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, externalTexture: {} }],
+ });
+
+ let bindGroup;
+ const useExternalTexture = () => {
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(passDescriptor);
+ passEncoder.setBindGroup(0, bindGroup);
+ passEncoder.end();
+ return commandEncoder.finish();
+ };
+
+ let externalTexture;
+ await startPlayingAndWaitForVideo(videoElement, async () => {
+ const source =
+ sourceType === 'VideoFrame'
+ ? await getVideoFrameFromVideoElement(t, videoElement)
+ : videoElement;
+ externalTexture = t.device.importExternalTexture({
+ source: source,
+ });
+ // Set `bindGroup` here, which will then be used in microtask1 and microtask3.
+ bindGroup = t.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [{ binding: 0, resource: externalTexture }],
+ });
+
+ const commandBuffer = useExternalTexture();
+ t.expectGPUError('validation', () => t.device.queue.submit([commandBuffer]), false);
+ t.expect(!externalTexture.expired);
+
+ if (sourceType === 'VideoFrame') {
+ source.close();
+ const commandBuffer = useExternalTexture();
+ t.expectGPUError('validation', () => t.device.queue.submit([commandBuffer]), true);
+ t.expect(externalTexture.expired);
+ }
+ });
+
+ if (sourceType === 'VideoElement') {
+ // Update new video frame.
+ await waitForNextFrame(videoElement, () => {
+ // VideoFrame is updated. GPUExternalTexture imported from HTMLVideoElement should be expired.
+ // Using the GPUExternalTexture should result in an error.
+ const commandBuffer = useExternalTexture();
+ t.expectGPUError('validation', () => t.device.queue.submit([commandBuffer]), true);
+ t.expect(externalTexture.expired);
+ });
+ }
+ });
+
+g.test('importExternalTexture,compute')
+ .desc(
+ `
+Tests that we can import an HTMLVideoElement/VideoFrame into a GPUExternalTexture and use it in a
+compute shader, for several combinations of video format and color space.
+`
+ )
+ .params(u =>
+ u //
+ .combine('sourceType', ['VideoElement', 'VideoFrame'])
+ .combineWithParams(kVideoExpectations)
+ )
+ .fn(async t => {
+ const sourceType = t.params.sourceType;
+ const { videoElement, videoInfo } = getVideoElementAndInfo(t, sourceType, t.params.videoName);
+
+ await startPlayingAndWaitForVideo(videoElement, async () => {
+ const source =
+ sourceType === 'VideoFrame'
+ ? await getVideoFrameFromVideoElement(
+ t,
+ videoElement,
+ getVideoColorSpaceInit(videoInfo.colorSpace)
+ )
+ : videoElement;
+ const externalTexture = t.device.importExternalTexture({
+ source: source,
+ });
+
+ const outputTexture = t.device.createTexture({
+ format: 'rgba8unorm',
+ size: [2, 1, 1],
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING,
+ });
+
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ // Shader will load a pixel near the upper left and lower right corners, which are then
+ // stored in storage texture.
+ module: t.device.createShaderModule({
+ code: `
+ @group(0) @binding(0) var t : texture_external;
+ @group(0) @binding(1) var outImage : texture_storage_2d<rgba8unorm, write>;
+
+ @compute @workgroup_size(1) fn main() {
+ var red : vec4<f32> = textureLoad(t, vec2<i32>(10,10));
+ textureStore(outImage, vec2<i32>(0, 0), red);
+ var green : vec4<f32> = textureLoad(t, vec2<i32>(70,118));
+ textureStore(outImage, vec2<i32>(1, 0), green);
+ return;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [
+ { binding: 0, resource: externalTexture },
+ { binding: 1, resource: outputTexture.createView() },
+ ],
+
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bg);
+ pass.dispatchWorkgroups(1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+
+ // Pixel loaded from top left corner should be red.
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ kFormat,
+ { x: 0, y: 0 },
+ {
+ exp: t.params._redExpectation,
+ }
+ );
+
+ // Pixel loaded from Bottom right corner should be green.
+ t.expectSinglePixelIn2DTexture(
+ outputTexture,
+ kFormat,
+ { x: 1, y: 0 },
+ {
+ exp: t.params._greenExpectation,
+ }
+ );
+
+ if (sourceType === 'VideoFrame') source.close();
+ });
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.html.js
new file mode 100644
index 0000000000..4ffb878130
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.html.js
@@ -0,0 +1,35 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { runRefTest } from './gpu_ref_test.js';
+runRefTest(async t => {
+ function draw(canvasId, format) {
+ const canvas = document.getElementById(canvasId);
+
+ const ctx = canvas.getContext('webgpu');
+ ctx.configure({
+ device: t.device,
+ format,
+ });
+
+ const colorAttachment = ctx.getCurrentTexture();
+ const colorAttachmentView = colorAttachment.createView();
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: colorAttachmentView,
+ clearValue: { r: 0.4, g: 1.0, b: 0.0, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ draw('cvs0', 'bgra8unorm');
+ draw('cvs1', 'rgba8unorm');
+ draw('cvs2', 'rgba16float');
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html
new file mode 100644
index 0000000000..3639d3ca82
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_clear.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_clear</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU cleared canvas should be presented correctly" />
+ <link rel="match" href="./ref/canvas_clear-ref.html" />
+ <canvas id="cvs0" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs1" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs2" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module" src="canvas_clear.html.js"></script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace.html.js
new file mode 100644
index 0000000000..2796ec292d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace.html.js
@@ -0,0 +1,93 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { kUnitCaseParamsBuilder } from '../../../common/framework/params_builder.js';
+import { Float16Array } from '../../../external/petamoriken/float16/float16.js';
+import { kCanvasAlphaModes, kCanvasColorSpaces } from '../../capability_info.js';
+
+import { runRefTest } from './gpu_ref_test.js';
+
+function bgra8UnormFromRgba8Unorm(rgba8Unorm) {
+ const bgra8Unorm = rgba8Unorm.slice();
+ for (let i = 0; i < bgra8Unorm.length; i += 4) {
+ [bgra8Unorm[i], bgra8Unorm[i + 2]] = [bgra8Unorm[i + 2], bgra8Unorm[i]];
+ }
+ return bgra8Unorm;
+}
+
+function rgba16floatFromRgba8unorm(rgba8Unorm) {
+ const rgba16Float = new Float16Array(rgba8Unorm.length);
+ for (let i = 0; i < rgba8Unorm.length; ++i) {
+ rgba16Float[i] = rgba8Unorm[i] / 255;
+ }
+ return rgba16Float;
+}
+
+export function runColorSpaceTest(format) {
+ runRefTest(async t => {
+ const device = t.device;
+
+ const kRGBA8UnormData = new Uint8Array([
+ 0,
+ 255,
+ 0,
+ 255,
+ 117,
+ 251,
+ 7,
+ 255,
+ 170,
+ 35,
+ 209,
+ 255,
+ 80,
+ 150,
+ 200,
+ 255,
+ ]);
+
+ const kBGRA8UnormData = bgra8UnormFromRgba8Unorm(kRGBA8UnormData);
+ const kRGBA16FloatData = rgba16floatFromRgba8unorm(kRGBA8UnormData);
+ const width = kRGBA8UnormData.length / 4;
+
+ const testData = {
+ rgba8unorm: kRGBA8UnormData,
+ bgra8unorm: kBGRA8UnormData,
+ rgba16float: kRGBA16FloatData,
+ };
+
+ function createCanvas(alphaMode, format, colorSpace) {
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = 1;
+ const context = canvas.getContext('webgpu');
+ context.configure({
+ device,
+ format,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
+ alphaMode,
+ colorSpace,
+ });
+
+ const textureData = testData[format];
+ const texture = context.getCurrentTexture();
+ device.queue.writeTexture(
+ { texture },
+ textureData.buffer,
+ {
+ bytesPerRow: textureData.byteLength,
+ },
+ { width: 4, height: 1 }
+ );
+
+ document.body.appendChild(canvas);
+ }
+
+ const u = kUnitCaseParamsBuilder
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('colorSpace', kCanvasColorSpaces);
+
+ for (const { alphaMode, colorSpace } of u) {
+ createCanvas(alphaMode, format, colorSpace);
+ }
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html
new file mode 100644
index 0000000000..c910c97b1d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_bgra8unorm.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_colorspace_bgra8unorm</title>
+ <meta charset="utf-8" />
+ <style>
+ canvas {
+ width: 128px;
+ height: 128px;
+ margin-right: 5px;
+ image-rendering: pixelated;
+ image-rendering: crisp-edges;
+ }
+ </style>
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU bgra8norm canvas with colorSpace set should be rendered correctly" />
+ <link rel="match" href="./ref/canvas_colorspace-ref.html" />
+ <script type="module">
+ import { runColorSpaceTest } from './canvas_colorspace.html.js';
+ runColorSpaceTest('bgra8unorm');
+ </script>
+ <body></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html
new file mode 100644
index 0000000000..7f57858e49
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba16float.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_colorspace_rgba16float</title>
+ <meta charset="utf-8" />
+ <style>
+ canvas {
+ width: 128px;
+ height: 128px;
+ margin-right: 5px;
+ image-rendering: pixelated;
+ image-rendering: crisp-edges;
+ }
+ </style>
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU rgba16float canvas with colorSpace set should be rendered correctly" />
+ <link rel="match" href="./ref/canvas_colorspace-ref.html" />
+ <meta name=fuzzy content="maxDifference=1;totalPixels=8192">
+ <script type="module">
+ import { runColorSpaceTest } from './canvas_colorspace.html.js';
+ runColorSpaceTest('rgba16float');
+ </script>
+ <body></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html
new file mode 100644
index 0000000000..e57e04ef5c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_colorspace_rgba8unorm.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_colorspace_rgba8unorm</title>
+ <meta charset="utf-8" />
+ <style>
+ canvas {
+ width: 128px;
+ height: 128px;
+ margin-right: 5px;
+ image-rendering: pixelated;
+ image-rendering: crisp-edges;
+ }
+ </style>
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU rgba8unorm canvas with colorSpace set should be rendered correctly" />
+ <link rel="match" href="./ref/canvas_colorspace-ref.html" />
+ <script type="module">
+ import { runColorSpaceTest } from './canvas_colorspace.html.js';
+ runColorSpaceTest('rgba8unorm');
+ </script>
+ <body></body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex.html.js
new file mode 100644
index 0000000000..5a4b7ccfd0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex.html.js
@@ -0,0 +1,768 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../common/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import { gammaDecompress, float32ToFloat16Bits } from '../../util/conversion.js';
+import { align } from '../../util/math.js';
+
+import { runRefTest } from './gpu_ref_test.js';
+
+export function run(format, targets) {
+ runRefTest(async t => {
+ let shaderValue = 0x66 / 0xff;
+ let isOutputSrgb = false;
+ switch (format) {
+ case 'bgra8unorm':
+ case 'rgba8unorm':
+ case 'rgba16float':
+ break;
+ case 'bgra8unorm-srgb':
+ case 'rgba8unorm-srgb':
+ // NOTE: "-srgb" cases haven't been tested (there aren't any .html files that use them).
+
+ // Reverse gammaCompress to get same value shader output as non-srgb formats:
+ shaderValue = gammaDecompress(shaderValue);
+ isOutputSrgb = true;
+ break;
+ default:
+ unreachable();
+ }
+
+ const shaderValueStr = shaderValue.toFixed(5);
+
+ function copyBufferToTexture(ctx) {
+ const rows = ctx.canvas.height;
+ const bytesPerPixel = kTextureFormatInfo[format].bytesPerBlock;
+ if (bytesPerPixel === undefined) {
+ unreachable();
+ }
+ const bytesPerRow = align(bytesPerPixel * ctx.canvas.width, 256);
+ const componentsPerPixel = 4;
+
+ const buffer = t.device.createBuffer({
+ mappedAtCreation: true,
+ size: rows * bytesPerRow,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ let red;
+ let green;
+ let blue;
+ let yellow;
+
+ const mapping = buffer.getMappedRange();
+ let data;
+ switch (format) {
+ case 'bgra8unorm':
+ case 'bgra8unorm-srgb':
+ {
+ data = new Uint8Array(mapping);
+ red = new Uint8Array([0x00, 0x00, 0x66, 0xff]);
+ green = new Uint8Array([0x00, 0x66, 0x00, 0xff]);
+ blue = new Uint8Array([0x66, 0x00, 0x00, 0xff]);
+ yellow = new Uint8Array([0x00, 0x66, 0x66, 0xff]);
+ }
+ break;
+ case 'rgba8unorm':
+ case 'rgba8unorm-srgb':
+ {
+ data = new Uint8Array(mapping);
+ red = new Uint8Array([0x66, 0x00, 0x00, 0xff]);
+ green = new Uint8Array([0x00, 0x66, 0x00, 0xff]);
+ blue = new Uint8Array([0x00, 0x00, 0x66, 0xff]);
+ yellow = new Uint8Array([0x66, 0x66, 0x00, 0xff]);
+ }
+ break;
+ case 'rgba16float':
+ {
+ data = new Uint16Array(mapping);
+ red = new Uint16Array([
+ float32ToFloat16Bits(0.4),
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(1.0),
+ ]);
+
+ green = new Uint16Array([
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(0.4),
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(1.0),
+ ]);
+
+ blue = new Uint16Array([
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(0.4),
+ float32ToFloat16Bits(1.0),
+ ]);
+
+ yellow = new Uint16Array([
+ float32ToFloat16Bits(0.4),
+ float32ToFloat16Bits(0.4),
+ float32ToFloat16Bits(0.0),
+ float32ToFloat16Bits(1.0),
+ ]);
+ }
+ break;
+ default:
+ unreachable();
+ }
+
+ for (let i = 0; i < ctx.canvas.width; ++i)
+ for (let j = 0; j < ctx.canvas.height; ++j) {
+ let pixel;
+ if (i < ctx.canvas.width / 2) {
+ if (j < ctx.canvas.height / 2) {
+ pixel = red;
+ } else {
+ pixel = blue;
+ }
+ } else {
+ if (j < ctx.canvas.height / 2) {
+ pixel = green;
+ } else {
+ pixel = yellow;
+ }
+ }
+ data.set(pixel, (i + j * (bytesPerRow / bytesPerPixel)) * componentsPerPixel);
+ }
+ buffer.unmap();
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToTexture({ buffer, bytesPerRow }, { texture: ctx.getCurrentTexture() }, [
+ ctx.canvas.width,
+ ctx.canvas.height,
+ 1,
+ ]);
+
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ function getImageBitmap(ctx) {
+ const data = new Uint8ClampedArray(ctx.canvas.width * ctx.canvas.height * 4);
+ for (let i = 0; i < ctx.canvas.width; ++i)
+ for (let j = 0; j < ctx.canvas.height; ++j) {
+ const offset = (i + j * ctx.canvas.width) * 4;
+ if (i < ctx.canvas.width / 2) {
+ if (j < ctx.canvas.height / 2) {
+ data.set([0x66, 0x00, 0x00, 0xff], offset);
+ } else {
+ data.set([0x00, 0x00, 0x66, 0xff], offset);
+ }
+ } else {
+ if (j < ctx.canvas.height / 2) {
+ data.set([0x00, 0x66, 0x00, 0xff], offset);
+ } else {
+ data.set([0x66, 0x66, 0x00, 0xff], offset);
+ }
+ }
+ }
+ const imageData = new ImageData(data, ctx.canvas.width, ctx.canvas.height);
+ return createImageBitmap(imageData);
+ }
+
+ function setupSrcTexture(imageBitmap) {
+ const [srcWidth, srcHeight] = [imageBitmap.width, imageBitmap.height];
+ const srcTexture = t.device.createTexture({
+ size: [srcWidth, srcHeight, 1],
+ format,
+ usage:
+ GPUTextureUsage.TEXTURE_BINDING |
+ GPUTextureUsage.RENDER_ATTACHMENT |
+ GPUTextureUsage.COPY_DST |
+ GPUTextureUsage.COPY_SRC,
+ });
+ t.device.queue.copyExternalImageToTexture({ source: imageBitmap }, { texture: srcTexture }, [
+ imageBitmap.width,
+ imageBitmap.height,
+ ]);
+
+ return srcTexture;
+ }
+
+ async function copyExternalImageToTexture(ctx) {
+ const imageBitmap = await getImageBitmap(ctx);
+ t.device.queue.copyExternalImageToTexture(
+ { source: imageBitmap },
+ { texture: ctx.getCurrentTexture() },
+ [imageBitmap.width, imageBitmap.height]
+ );
+ }
+
+ async function copyTextureToTexture(ctx) {
+ const imageBitmap = await getImageBitmap(ctx);
+ const srcTexture = setupSrcTexture(imageBitmap);
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyTextureToTexture(
+ { texture: srcTexture, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ { texture: ctx.getCurrentTexture(), mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
+ [imageBitmap.width, imageBitmap.height, 1]
+ );
+
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ async function DrawTextureSample(ctx) {
+ const imageBitmap = await getImageBitmap(ctx);
+ const srcTexture = setupSrcTexture(imageBitmap);
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+struct VertexOutput {
+ @builtin(position) Position : vec4<f32>,
+ @location(0) fragUV : vec2<f32>,
+}
+
+@vertex
+fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0));
+
+ var uv = array<vec2<f32>, 6>(
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(0.0, 0.0));
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ output.fragUV = uv[VertexIndex];
+ return output;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ // NOTE: "-srgb" cases haven't been tested (there aren't any .html files that use them).
+ code: `
+@group(0) @binding(0) var mySampler: sampler;
+@group(0) @binding(1) var myTexture: texture_2d<f32>;
+
+fn gammaDecompress(n: f32) -> f32 {
+ var r = n;
+ if (r <= 0.04045) {
+ r = r * 25.0 / 323.0;
+ } else {
+ r = pow((200.0 * r + 11.0) / 121.0, 12.0 / 5.0);
+ }
+ r = clamp(r, 0.0, 1.0);
+ return r;
+}
+
+@fragment
+fn srgbMain(@location(0) fragUV: vec2<f32>) -> @location(0) vec4<f32> {
+ var result = textureSample(myTexture, mySampler, fragUV);
+ result.r = gammaDecompress(result.r);
+ result.g = gammaDecompress(result.g);
+ result.b = gammaDecompress(result.b);
+ return result;
+}
+
+@fragment
+fn linearMain(@location(0) fragUV: vec2<f32>) -> @location(0) vec4<f32> {
+ return textureSample(myTexture, mySampler, fragUV);
+}
+ `,
+ }),
+ entryPoint: isOutputSrgb ? 'srgbMain' : 'linearMain',
+ targets: [{ format }],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ const sampler = t.device.createSampler({
+ magFilter: 'nearest',
+ minFilter: 'nearest',
+ });
+
+ const uniformBindGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: sampler,
+ },
+ {
+ binding: 1,
+ resource: srcTexture.createView(),
+ },
+ ],
+ });
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: ctx.getCurrentTexture().createView(),
+
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, uniformBindGroup);
+ passEncoder.draw(6, 1, 0, 0);
+ passEncoder.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+ }
+
+ function DrawVertexColor(ctx) {
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+struct VertexOutput {
+ @builtin(position) Position : vec4<f32>,
+ @location(0) fragColor : vec4<f32>,
+}
+
+@vertex
+fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 0.5, 0.5),
+ vec2<f32>( 0.5, -0.5),
+ vec2<f32>(-0.5, -0.5),
+ vec2<f32>( 0.5, 0.5),
+ vec2<f32>(-0.5, -0.5),
+ vec2<f32>(-0.5, 0.5));
+
+ var offset = array<vec2<f32>, 4>(
+ vec2<f32>( -0.5, 0.5),
+ vec2<f32>( 0.5, 0.5),
+ vec2<f32>(-0.5, -0.5),
+ vec2<f32>( 0.5, -0.5));
+
+ var color = array<vec4<f32>, 4>(
+ vec4<f32>(${shaderValueStr}, 0.0, 0.0, 1.0),
+ vec4<f32>(0.0, ${shaderValueStr}, 0.0, 1.0),
+ vec4<f32>(0.0, 0.0, ${shaderValueStr}, 1.0),
+ vec4<f32>(${shaderValueStr}, ${shaderValueStr}, 0.0, 1.0));
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex % 6u] + offset[VertexIndex / 6u], 0.0, 1.0);
+ output.fragColor = color[VertexIndex / 6u];
+ return output;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+@fragment
+fn main(@location(0) fragColor: vec4<f32>) -> @location(0) vec4<f32> {
+ return fragColor;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: ctx.getCurrentTexture().createView(),
+
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.draw(24, 1, 0, 0);
+ passEncoder.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+ }
+
+ function DrawFragcoord(ctx) {
+ const halfCanvasWidthStr = (ctx.canvas.width / 2).toFixed();
+ const halfCanvasHeightStr = (ctx.canvas.height / 2).toFixed();
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+struct VertexOutput {
+ @builtin(position) Position : vec4<f32>
+}
+
+@vertex
+fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0));
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ return output;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+@group(0) @binding(0) var mySampler: sampler;
+@group(0) @binding(1) var myTexture: texture_2d<f32>;
+
+@fragment
+fn main(@builtin(position) fragcoord: vec4<f32>) -> @location(0) vec4<f32> {
+ var coord = vec2<u32>(floor(fragcoord.xy));
+ var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ if (coord.x < ${halfCanvasWidthStr}u) {
+ if (coord.y < ${halfCanvasHeightStr}u) {
+ color.r = ${shaderValueStr};
+ } else {
+ color.b = ${shaderValueStr};
+ }
+ } else {
+ if (coord.y < ${halfCanvasHeightStr}u) {
+ color.g = ${shaderValueStr};
+ } else {
+ color.r = ${shaderValueStr};
+ color.g = ${shaderValueStr};
+ }
+ }
+ return color;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: ctx.getCurrentTexture().createView(),
+
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.draw(6, 1, 0, 0);
+ passEncoder.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+ }
+
+ function FragmentTextureStore(ctx) {
+ const halfCanvasWidthStr = (ctx.canvas.width / 2).toFixed();
+ const halfCanvasHeightStr = (ctx.canvas.height / 2).toFixed();
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+struct VertexOutput {
+ @builtin(position) Position : vec4<f32>
+}
+
+@vertex
+fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+ var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>( 1.0, -1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>( 1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(-1.0, 1.0));
+
+ var output : VertexOutput;
+ output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
+ return output;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+@group(0) @binding(0) var outImage : texture_storage_2d<${format}, write>;
+
+@fragment
+fn main(@builtin(position) fragcoord: vec4<f32>) -> @location(0) vec4<f32> {
+ var coord = vec2<u32>(floor(fragcoord.xy));
+ var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ if (coord.x < ${halfCanvasWidthStr}u) {
+ if (coord.y < ${halfCanvasHeightStr}u) {
+ color.r = ${shaderValueStr};
+ } else {
+ color.b = ${shaderValueStr};
+ }
+ } else {
+ if (coord.y < ${halfCanvasHeightStr}u) {
+ color.g = ${shaderValueStr};
+ } else {
+ color.r = ${shaderValueStr};
+ color.g = ${shaderValueStr};
+ }
+ }
+ textureStore(outImage, vec2<i32>(coord), color);
+ return color;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [{ binding: 0, resource: ctx.getCurrentTexture().createView() }],
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const outputTexture = t.device.createTexture({
+ format,
+ size: [ctx.canvas.width, ctx.canvas.height, 1],
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
+ });
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: outputTexture.createView(),
+
+ clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.setBindGroup(0, bg);
+ passEncoder.draw(6, 1, 0, 0);
+ passEncoder.end();
+ t.device.queue.submit([commandEncoder.finish()]);
+ }
+
+ function ComputeWorkgroup1x1TextureStore(ctx) {
+ const halfCanvasWidthStr = (ctx.canvas.width / 2).toFixed();
+ const halfCanvasHeightStr = (ctx.canvas.height / 2).toFixed();
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+@group(0) @binding(0) var outImage : texture_storage_2d<${format}, write>;
+
+@compute @workgroup_size(1, 1, 1)
+fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {
+ var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ if (GlobalInvocationID.x < ${halfCanvasWidthStr}u) {
+ if (GlobalInvocationID.y < ${halfCanvasHeightStr}u) {
+ color.r = ${shaderValueStr};
+ } else {
+ color.b = ${shaderValueStr};
+ }
+ } else {
+ if (GlobalInvocationID.y < ${halfCanvasHeightStr}u) {
+ color.g = ${shaderValueStr};
+ } else {
+ color.r = ${shaderValueStr};
+ color.g = ${shaderValueStr};
+ }
+ }
+ textureStore(outImage, vec2<i32>(GlobalInvocationID.xy), color);
+ return;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [{ binding: 0, resource: ctx.getCurrentTexture().createView() }],
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bg);
+ pass.dispatchWorkgroups(ctx.canvas.width, ctx.canvas.height, 1);
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ function ComputeWorkgroup16x16TextureStore(ctx) {
+ const canvasWidthStr = ctx.canvas.width.toFixed();
+ const canvasHeightStr = ctx.canvas.height.toFixed();
+ const halfCanvasWidthStr = (ctx.canvas.width / 2).toFixed();
+ const halfCanvasHeightStr = (ctx.canvas.height / 2).toFixed();
+ const pipeline = t.device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: t.device.createShaderModule({
+ code: `
+@group(0) @binding(0) var outImage : texture_storage_2d<${format}, write>;
+
+@compute @workgroup_size(16, 16, 1)
+fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {
+ if (GlobalInvocationID.x >= ${canvasWidthStr}u ||
+ GlobalInvocationID.y >= ${canvasHeightStr}u) {
+ return;
+ }
+ var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ if (GlobalInvocationID.x < ${halfCanvasWidthStr}u) {
+ if (GlobalInvocationID.y < ${halfCanvasHeightStr}u) {
+ color.r = ${shaderValueStr};
+ } else {
+ color.b = ${shaderValueStr};
+ }
+ } else {
+ if (GlobalInvocationID.y < ${halfCanvasHeightStr}u) {
+ color.g = ${shaderValueStr};
+ } else {
+ color.r = ${shaderValueStr};
+ color.g = ${shaderValueStr};
+ }
+ }
+ textureStore(outImage, vec2<i32>(GlobalInvocationID.xy), color);
+ return;
+}
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const bg = t.device.createBindGroup({
+ entries: [{ binding: 0, resource: ctx.getCurrentTexture().createView() }],
+ layout: pipeline.getBindGroupLayout(0),
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bg);
+ pass.dispatchWorkgroups(
+ align(ctx.canvas.width, 16) / 16,
+ align(ctx.canvas.height, 16) / 16,
+ 1
+ );
+
+ pass.end();
+ t.device.queue.submit([encoder.finish()]);
+ }
+
+ for (const { cvs, writeCanvasMethod } of targets) {
+ const ctx = cvs.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ let usage;
+ switch (writeCanvasMethod) {
+ case 'copyBufferToTexture':
+ case 'copyTextureToTexture':
+ usage = GPUTextureUsage.COPY_DST;
+ break;
+ case 'copyExternalImageToTexture':
+ usage = GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;
+ break;
+ case 'DrawTextureSample':
+ case 'DrawVertexColor':
+ case 'DrawFragcoord':
+ usage = GPUTextureUsage.RENDER_ATTACHMENT;
+ break;
+ case 'FragmentTextureStore':
+ case 'ComputeWorkgroup1x1TextureStore':
+ case 'ComputeWorkgroup16x16TextureStore':
+ usage = GPUTextureUsage.STORAGE_BINDING;
+ break;
+ default:
+ unreachable();
+ }
+
+ ctx.configure({
+ device: t.device,
+ format,
+ usage,
+ });
+
+ switch (writeCanvasMethod) {
+ case 'copyBufferToTexture':
+ copyBufferToTexture(ctx);
+ break;
+ case 'copyExternalImageToTexture':
+ await copyExternalImageToTexture(ctx);
+ break;
+ case 'copyTextureToTexture':
+ await copyTextureToTexture(ctx);
+ break;
+ case 'DrawTextureSample':
+ await DrawTextureSample(ctx);
+ break;
+ case 'DrawVertexColor':
+ DrawVertexColor(ctx);
+ break;
+ case 'DrawFragcoord':
+ DrawFragcoord(ctx);
+ break;
+ case 'FragmentTextureStore':
+ FragmentTextureStore(ctx);
+ break;
+ case 'ComputeWorkgroup1x1TextureStore':
+ ComputeWorkgroup1x1TextureStore(ctx);
+ break;
+ case 'ComputeWorkgroup16x16TextureStore':
+ ComputeWorkgroup16x16TextureStore(ctx);
+ break;
+ default:
+ unreachable();
+ }
+ }
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html
new file mode 100644
index 0000000000..d378bdfcf5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_copy.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_bgra8unorm_copy</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_copy_buffer_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_texture_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_external_image_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('bgra8unorm', [
+ { cvs: cvs_copy_buffer_to_texture, writeCanvasMethod: 'copyBufferToTexture' },
+ { cvs: cvs_copy_texture_to_texture, writeCanvasMethod: 'copyTextureToTexture' },
+ { cvs: cvs_copy_external_image_to_texture, writeCanvasMethod: 'copyExternalImageToTexture' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html
new file mode 100644
index 0000000000..99049e6e32
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm_draw.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_bgra8unorm_draw</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_draw_texture_sample" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_vertex_color" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_fragcoord" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('bgra8unorm', [
+ { cvs: cvs_draw_texture_sample, writeCanvasMethod: 'DrawTextureSample' },
+ { cvs: cvs_draw_vertex_color, writeCanvasMethod: 'DrawVertexColor' },
+ { cvs: cvs_draw_fragcoord, writeCanvasMethod: 'DrawFragcoord' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html
new file mode 100644
index 0000000000..400afa121b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_copy.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba16float_copy</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_copy_buffer_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_texture_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_external_image_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba16float', [
+ { cvs: cvs_copy_buffer_to_texture, writeCanvasMethod: 'copyBufferToTexture' },
+ { cvs: cvs_copy_texture_to_texture, writeCanvasMethod: 'copyTextureToTexture' },
+ { cvs: cvs_copy_external_image_to_texture, writeCanvasMethod: 'copyExternalImageToTexture' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html
new file mode 100644
index 0000000000..a647fc2956
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_draw.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba16float_draw</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_draw_texture_sample" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_vertex_color" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_fragcoord" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba16float', [
+ { cvs: cvs_draw_texture_sample, writeCanvasMethod: 'DrawTextureSample' },
+ { cvs: cvs_draw_vertex_color, writeCanvasMethod: 'DrawVertexColor' },
+ { cvs: cvs_draw_fragcoord, writeCanvasMethod: 'DrawFragcoord' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html
new file mode 100644
index 0000000000..b812129b0b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba16float_store.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba16float_store</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_fragment_texture_store" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_compute_texture_store_1" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_compute_texture_store_2" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba16float', [
+ { cvs: cvs_fragment_texture_store, writeCanvasMethod: 'FragmentTextureStore' },
+ { cvs: cvs_compute_texture_store_1, writeCanvasMethod: 'ComputeWorkgroup1x1TextureStore' },
+ { cvs: cvs_compute_texture_store_2, writeCanvasMethod: 'ComputeWorkgroup16x16TextureStore' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html
new file mode 100644
index 0000000000..d2570a3bdf
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_copy.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba8unorm_copy</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_copy_buffer_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_texture_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_copy_external_image_to_texture" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba8unorm', [
+ { cvs: cvs_copy_buffer_to_texture, writeCanvasMethod: 'copyBufferToTexture' },
+ { cvs: cvs_copy_texture_to_texture, writeCanvasMethod: 'copyTextureToTexture' },
+ { cvs: cvs_copy_external_image_to_texture, writeCanvasMethod: 'copyExternalImageToTexture' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html
new file mode 100644
index 0000000000..647a829259
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_draw.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba8unorm_draw</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_draw_texture_sample" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_vertex_color" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_draw_fragcoord" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba8unorm', [
+ { cvs: cvs_draw_texture_sample, writeCanvasMethod: 'DrawTextureSample' },
+ { cvs: cvs_draw_vertex_color, writeCanvasMethod: 'DrawVertexColor' },
+ { cvs: cvs_draw_fragcoord, writeCanvasMethod: 'DrawFragcoord' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html
new file mode 100644
index 0000000000..b82745658e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_complex_rgba8unorm_store.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_rgba8unorm_store</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs_fragment_texture_store" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_compute_texture_store_1" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs_compute_texture_store_2" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+
+ <script type="module">
+ import { run } from './canvas_complex.html.js';
+ run('rgba8unorm', [
+ { cvs: cvs_fragment_texture_store, writeCanvasMethod: 'FragmentTextureStore' },
+ { cvs: cvs_compute_texture_store_1, writeCanvasMethod: 'ComputeWorkgroup1x1TextureStore' },
+ { cvs: cvs_compute_texture_store_2, writeCanvasMethod: 'ComputeWorkgroup16x16TextureStore' },
+ ]);
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha.html.js
new file mode 100644
index 0000000000..df3dad236e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha.html.js
@@ -0,0 +1,175 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert, unreachable } from '../../../common/util/util.js';
+import { runRefTest } from './gpu_ref_test.js';
+
+export function run(format, alphaMode, writeCanvasMethod) {
+ runRefTest(async t => {
+ const module = t.device.createShaderModule({
+ code: `
+struct VertexOutput {
+@builtin(position) Position : vec4<f32>,
+@location(0) fragColor : vec4<f32>,
+}
+
+@vertex
+fn mainVS(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
+var pos = array<vec2<f32>, 6>(
+ vec2<f32>( 0.75, 0.75),
+ vec2<f32>( 0.75, -0.75),
+ vec2<f32>(-0.75, -0.75),
+ vec2<f32>( 0.75, 0.75),
+ vec2<f32>(-0.75, -0.75),
+ vec2<f32>(-0.75, 0.75));
+
+var offset = array<vec2<f32>, 4>(
+vec2<f32>( -0.25, 0.25),
+vec2<f32>( 0.25, 0.25),
+vec2<f32>(-0.25, -0.25),
+vec2<f32>( 0.25, -0.25));
+
+// Alpha channel value is set to 0.5 regardless of the canvas alpha mode.
+// For 'opaque' mode, it shouldn't affect the end result, as the alpha channel should always get cleared to 1.0.
+var color = array<vec4<f32>, 4>(
+ vec4<f32>(0.4, 0.0, 0.0, 0.5),
+ vec4<f32>(0.0, 0.4, 0.0, 0.5),
+ vec4<f32>(0.0, 0.0, 0.4, 0.5),
+ vec4<f32>(0.4, 0.4, 0.0, 0.5)); // 0.4 -> 0x66
+
+var output : VertexOutput;
+output.Position = vec4<f32>(pos[VertexIndex % 6u] + offset[VertexIndex / 6u], 0.0, 1.0);
+output.fragColor = color[VertexIndex / 6u];
+return output;
+}
+
+@fragment
+fn mainFS(@location(0) fragColor: vec4<f32>) -> @location(0) vec4<f32> {
+return fragColor;
+}
+ `,
+ });
+
+ document.querySelectorAll('canvas').forEach(canvas => {
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ switch (format) {
+ case 'bgra8unorm':
+ case 'bgra8unorm-srgb':
+ case 'rgba8unorm':
+ case 'rgba8unorm-srgb':
+ case 'rgba16float':
+ break;
+ default:
+ unreachable();
+ }
+
+ let usage = 0;
+ switch (writeCanvasMethod) {
+ case 'draw':
+ usage = GPUTextureUsage.RENDER_ATTACHMENT;
+ break;
+ case 'copy':
+ usage = GPUTextureUsage.COPY_DST;
+ break;
+ }
+
+ ctx.configure({
+ device: t.device,
+ format,
+ usage,
+ alphaMode,
+ });
+
+ // The blending behavior here is to mimic 2d context blending behavior
+ // of drawing rects in order
+ // https://drafts.fxtf.org/compositing/#porterduffcompositingoperators_srcover
+ const kBlendStateSourceOver = {
+ color: {
+ srcFactor: 'src-alpha',
+ dstFactor: 'one-minus-src-alpha',
+ operation: 'add',
+ },
+ alpha: {
+ srcFactor: 'one',
+ dstFactor: 'one-minus-src-alpha',
+ operation: 'add',
+ },
+ };
+
+ const pipeline = t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'mainVS',
+ },
+ fragment: {
+ module,
+ entryPoint: 'mainFS',
+ targets: [
+ {
+ format,
+ blend: { premultiplied: kBlendStateSourceOver, opaque: undefined }[alphaMode],
+ },
+ ],
+ },
+ primitive: {
+ topology: 'triangle-list',
+ },
+ });
+
+ let renderTarget;
+ switch (writeCanvasMethod) {
+ case 'draw':
+ renderTarget = ctx.getCurrentTexture();
+ break;
+ case 'copy':
+ renderTarget = t.device.createTexture({
+ size: [ctx.canvas.width, ctx.canvas.height],
+ format,
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ break;
+ }
+
+ const renderPassDescriptor = {
+ colorAttachments: [
+ {
+ view: renderTarget.createView(),
+ clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ };
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+ passEncoder.setPipeline(pipeline);
+ passEncoder.draw(6, 1, 0, 0);
+ passEncoder.draw(6, 1, 6, 0);
+ passEncoder.draw(6, 1, 12, 0);
+ passEncoder.draw(6, 1, 18, 0);
+ passEncoder.end();
+
+ switch (writeCanvasMethod) {
+ case 'draw':
+ break;
+ case 'copy':
+ commandEncoder.copyTextureToTexture(
+ {
+ texture: renderTarget,
+ },
+ {
+ texture: ctx.getCurrentTexture(),
+ },
+ [ctx.canvas.width, ctx.canvas.height]
+ );
+
+ break;
+ }
+
+ t.device.queue.submit([commandEncoder.finish()]);
+ });
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html
new file mode 100644
index 0000000000..60e8417c16
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_copy.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_bgra8unorm_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('bgra8unorm', 'opaque', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html
new file mode 100644
index 0000000000..c0280a2a99
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_opaque_draw.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_bgra8unorm_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('bgra8unorm', 'opaque', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html
new file mode 100644
index 0000000000..70920dc0e6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_copy.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_bgra8unorm_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('bgra8unorm', 'premultiplied', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html
new file mode 100644
index 0000000000..d12751fac2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_bgra8unorm_premultiplied_draw.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_bgra8unorm_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('bgra8unorm', 'premultiplied', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html
new file mode 100644
index 0000000000..4471f08480
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_copy.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba16float_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba16float', 'opaque', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html
new file mode 100644
index 0000000000..11f0e73ec2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_opaque_draw.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba16float_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba16float', 'opaque', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html
new file mode 100644
index 0000000000..ed722013c1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_copy.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba16float_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba16float', 'premultiplied', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html
new file mode 100644
index 0000000000..8a028b168e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba16float_premultiplied_draw.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba16float_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba16float', 'premultiplied', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html
new file mode 100644
index 0000000000..7147631d19
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_copy.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba8unorm_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba8unorm', 'opaque', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html
new file mode 100644
index 0000000000..ec2bb05ed3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_opaque_draw.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba8unorm_opaque</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_opaque-ref.html" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba8unorm', 'opaque', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html
new file mode 100644
index 0000000000..fa938aba41
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_copy.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba8unorm_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba8unorm', 'premultiplied', 'copy');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html
new file mode 100644
index 0000000000..b62e71054c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_composite_alpha_rgba8unorm_premultiplied_draw.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_composite_alpha_rgba8unorm_premultiplied</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_composite_alpha_premultiplied-ref.html" />
+ <meta name=fuzzy content="maxDifference=0-2;totalPixels=0-400">
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script type="module">
+ import { run } from './canvas_composite_alpha.html.js';
+ run('rgba8unorm', 'premultiplied', 'draw');
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.html.js
new file mode 100644
index 0000000000..a661cf1b66
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.html.js
@@ -0,0 +1,80 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { runRefTest } from './gpu_ref_test.js';
+runRefTest(async t => {
+ const device = t.device;
+ const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
+
+ const module = device.createShaderModule({
+ code: `
+ @vertex fn vs(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 3>(
+ vec2(-1.0, 3.0),
+ vec2(-1.0,-1.0),
+ vec2( 3.0,-1.0)
+ );
+
+ return vec4(pos[VertexIndex], 0.0, 1.0);
+ }
+
+ @fragment fn fs(
+ @builtin(position) Pos : vec4<f32>
+ ) -> @location(0) vec4<f32> {
+ let black = vec4f(0, 0, 0, 1);
+ let white = vec4f(1, 1, 1, 1);
+ let iPos = vec4u(Pos);
+ let check = (iPos.x + iPos.y) & 1;
+ return mix(black, white, f32(check));
+ }
+ `,
+ });
+
+ const pipeline = device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'vs',
+ },
+ fragment: {
+ module,
+ entryPoint: 'fs',
+ targets: [{ format: presentationFormat }],
+ },
+ });
+
+ function draw(selector, alphaMode) {
+ const canvas = document.querySelector(selector);
+ const context = canvas.getContext('webgpu');
+ context.configure({
+ device,
+ format: presentationFormat,
+ alphaMode,
+ });
+
+ const encoder = device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: context.getCurrentTexture().createView(),
+ clearValue: [0.0, 0.0, 0.0, 0.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.draw(3);
+ pass.end();
+
+ device.queue.submit([encoder.finish()]);
+ }
+
+ draw('#elem1', 'premultiplied');
+ draw('#elem2', 'premultiplied');
+ draw('#elem3', 'premultiplied');
+ draw('#elem4', 'opaque');
+ draw('#elem5', 'opaque');
+ draw('#elem6', 'opaque');
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html
new file mode 100644
index 0000000000..f51145645b
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/canvas_image_rendering.https.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_image_rendering</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU canvas with image-rendering set should be rendered correctly" />
+ <link rel="match" href="./ref/canvas_image_rendering-ref.html" />
+ <canvas id="elem1" width="64" height="64" style="width: 99px; height: 99px;"></canvas>
+ <canvas id="elem2" width="64" height="64" style="width: 99px; height: 99px; image-rendering: pixelated;"></canvas>
+ <canvas id="elem3" width="64" height="64" style="width: 99px; height: 99px; image-rendering: crisp-edges"></canvas>
+ <canvas id="elem4" width="64" height="64" style="width: 99px; height: 99px;"></canvas>
+ <canvas id="elem5" width="64" height="64" style="width: 99px; height: 99px; image-rendering: pixelated;"></canvas>
+ <canvas id="elem6" width="64" height="64" style="width: 99px; height: 99px; image-rendering: crisp-edges"></canvas>
+ <script type="module" src="canvas_image_rendering.html.js"></script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/create-pattern-data-url.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/create-pattern-data-url.js
new file mode 100644
index 0000000000..e6e9019851
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/create-pattern-data-url.js
@@ -0,0 +1,20 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ // creates a 4x4 pattern
+export default function createPatternDataURL() {
+ const patternSize = 4;
+ const ctx = document.createElement('canvas').getContext('2d');
+ ctx.canvas.width = patternSize;
+ ctx.canvas.height = patternSize;
+
+ const b = [0, 0, 0, 255];
+ const t = [0, 0, 0, 0];
+ const r = [255, 0, 0, 255];
+ const g = [0, 255, 0, 255];
+
+ const imageData = new ImageData(patternSize, patternSize);
+
+ imageData.data.set([b, t, t, r, t, b, g, t, t, r, b, t, g, t, t, b].flat());
+ ctx.putImageData(imageData, 0, 0);
+ return { patternSize, imageData, dataURL: ctx.canvas.toDataURL() };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/gpu_ref_test.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/gpu_ref_test.js
new file mode 100644
index 0000000000..56ac1f2a33
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/gpu_ref_test.js
@@ -0,0 +1,23 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { assert } from '../../../common/util/util.js';
+import { takeScreenshotDelayed } from '../../../common/util/wpt_reftest_wait.js';
+
+export function runRefTest(fn) {
+ void (async () => {
+ assert(
+ typeof navigator !== 'undefined' && navigator.gpu !== undefined,
+ 'No WebGPU implementation found'
+ );
+
+ const adapter = await navigator.gpu.requestAdapter();
+ assert(adapter !== null);
+ const device = await adapter.requestDevice();
+ assert(device !== null);
+ const queue = device.queue;
+
+ await fn({ device, queue });
+
+ takeScreenshotDelayed(50);
+ })();
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html
new file mode 100644
index 0000000000..e37b78c3a6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_clear-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU canvas_clear (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <canvas id="cvs0" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs1" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs2" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script>
+ function draw(canvas) {
+ var c = document.getElementById(canvas);
+ var ctx = c.getContext('2d');
+ ctx.fillStyle = '#66FF00';
+ ctx.fillRect(0, 0, c.width, c.height);
+ }
+
+ draw('cvs0');
+ draw('cvs1');
+ draw('cvs2');
+
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html
new file mode 100644
index 0000000000..a6da9f6748
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU canvas_colorspace (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <style>
+ canvas {
+ width: 128px;
+ height: 128px;
+ margin-right: 5px;
+ image-rendering: pixelated;
+ image-rendering: crisp-edges;
+ }
+ </style>
+ <body></body>
+ <script type="module" src="canvas_colorspace-ref.html.js"></script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html.js
new file mode 100644
index 0000000000..10b700248c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html.js
@@ -0,0 +1,50 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { kUnitCaseParamsBuilder } from '../../../../common/framework/params_builder.js';
+import { kCanvasAlphaModes, kCanvasColorSpaces } from '../../../capability_info.js';
+
+const kRGBAData = new Uint8Array([
+ 0,
+ 255,
+ 0,
+ 255,
+ 117,
+ 251,
+ 7,
+ 255,
+ 170,
+ 35,
+ 209,
+ 255,
+ 80,
+ 150,
+ 200,
+ 255,
+]);
+
+const width = kRGBAData.length / 4;
+
+function createCanvas(colorSpace) {
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = 1;
+ const context = canvas.getContext('2d', {
+ colorSpace,
+ });
+
+ const imgData = context.getImageData(0, 0, width, 1);
+ imgData.data.set(kRGBAData);
+ context.putImageData(imgData, 0, 0);
+
+ document.body.appendChild(canvas);
+}
+
+const u = kUnitCaseParamsBuilder
+ .combine('alphaMode', kCanvasAlphaModes)
+ .combine('colorSpace', kCanvasColorSpaces);
+
+// Generate reference canvases for all combinations from the test.
+// We only need colorSpace to generate the correct reference.
+for (const { colorSpace } of u) {
+ createCanvas(colorSpace);
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html
new file mode 100644
index 0000000000..b1d46c108a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_complex-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU canvas_complex (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <canvas id="cvs0" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs1" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="cvs2" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script>
+ function draw(ctx) {
+ ctx.fillStyle = '#660000';
+ ctx.fillRect(0, 0, 10, 10);
+ ctx.fillStyle = '#006600';
+ ctx.fillRect(10, 0, 10, 10);
+ ctx.fillStyle = '#000066';
+ ctx.fillRect(0, 10, 10, 10);
+ ctx.fillStyle = '#666600';
+ ctx.fillRect(10, 10, 10, 10);
+ }
+
+ draw(cvs0.getContext('2d'));
+ draw(cvs1.getContext('2d'));
+ draw(cvs2.getContext('2d'));
+
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html
new file mode 100644
index 0000000000..94b9486514
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_opaque-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU canvas_composite_alpha_premultiplied (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script>
+ document.querySelectorAll('canvas').forEach(canvas => {
+ const ctx = canvas.getContext('2d');
+ ctx.globalAlpha = 1.0;
+ ctx.fillStyle = '#660000';
+ ctx.fillRect(0, 0, 15, 15);
+ ctx.fillStyle = '#006600';
+ ctx.fillRect(5, 0, 15, 15);
+ ctx.fillStyle = '#000066';
+ ctx.fillRect(0, 5, 15, 20);
+ ctx.fillStyle = '#666600';
+ ctx.fillRect(5, 5, 20, 20);
+ });
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html
new file mode 100644
index 0000000000..635625ecc7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_composite_alpha_premultiplied-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU canvas_composite_alpha_premultiplied (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <style>
+ body { background-color: #F0E68C; }
+ #c-canvas { background-color: #8CF0E6; }
+ </style>
+ <canvas id="c-body" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <canvas id="c-canvas" width="20" height="20" style="width: 20px; height: 20px;"></canvas>
+ <script>
+ document.querySelectorAll('canvas').forEach(canvas => {
+ const ctx = canvas.getContext('2d');
+ ctx.globalAlpha = 0.5;
+ ctx.fillStyle = '#660000';
+ ctx.fillRect(0, 0, 15, 15);
+ ctx.fillStyle = '#006600';
+ ctx.fillRect(5, 0, 15, 15);
+ ctx.fillStyle = '#000066';
+ ctx.fillRect(0, 5, 15, 20);
+ ctx.fillStyle = '#666600';
+ ctx.fillRect(5, 5, 20, 20);
+ });
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html
new file mode 100644
index 0000000000..f9eca704e8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/canvas_image_rendering-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU canvas_image_rendering (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <img id="elem1" width="64" height="64" style="width: 99px; height: 99px;">
+ <img id="elem2" width="64" height="64" style="width: 99px; height: 99px; image-rendering: pixelated;">
+ <img id="elem3" width="64" height="64" style="width: 99px; height: 99px; image-rendering: crisp-edges">
+ <img id="elem4" width="64" height="64" style="width: 99px; height: 99px;">
+ <img id="elem5" width="64" height="64" style="width: 99px; height: 99px; image-rendering: pixelated;">
+ <img id="elem6" width="64" height="64" style="width: 99px; height: 99px; image-rendering: crisp-edges">
+ <script type="module">
+ import { takeScreenshotDelayed } from '../../../../common/util/wpt_reftest_wait.js';
+
+ (async () => {
+ const dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAKdJREFUeF7t28kJwDAQA0Cp/6I3hJAqNK/kazDr2atJ7u7S9v3Z+76nnz18m7oBboAYIAZMRv//1fMKcAAHkCAJLuYAXoEv8ZMLcAAHcAAHcAAHjBZEOeBSDuAADuAADuAADtjrCqsIqQh98xAkSIIkSIIkSIIkSIKrYzJ6gyRIgiRIgiRIgiRIgiRoZ2hwYcp8gKqwSVF9AXuD9gbtDdobXGWw7nCbB5+MQQlHipKKAAAAAElFTkSuQmCC';
+ await Promise.all([...document.querySelectorAll('img')].map(img => {
+ img.src = dataURL;
+ return img.decode();
+ }));
+
+ takeScreenshotDelayed(50);
+ })();
+ </script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html
new file mode 100644
index 0000000000..5259a25c27
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/ref/resize_observer-ref.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+ <title>WebGPU ResizeObserver test (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <style>
+ .outer {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ }
+ .outer>* {
+ display: block;
+ height: 100px;
+ }
+ </style>
+ <body>
+ <div id="dpr"></div>
+ <div class="outer"></div>
+ <script type="module">
+ import { takeScreenshotDelayed } from '../../../../common/util/wpt_reftest_wait.js';
+ import createPatternDataURL from '../create-pattern-data-url.js';
+
+ (async () => {
+ const {patternSize, dataURL} = createPatternDataURL();
+
+ document.querySelector('#dpr').textContent = `dpr: ${devicePixelRatio}`;
+
+ /**
+ * Set the pattern's size on this element so that it draws where
+ * 1 pixel in the pattern maps to 1 devicePixel.
+ */
+ function setPattern(elem) {
+ const oneDevicePixel = 1 / devicePixelRatio;
+ const patternPixels = oneDevicePixel * patternSize;
+ elem.style.backgroundImage = `url("${dataURL}")`;
+ elem.style.backgroundSize = `${patternPixels}px ${patternPixels}px`;
+ }
+
+ /*
+ This ref creates elements like this
+ <body>
+ <div class="outer">
+ <div></div>
+ <div></div>
+ <div></div>
+ ...
+ </div>
+ </body>
+ Where the outer div is a flexbox centering the child elements.
+ Each of the child elements is set to a different width in percent.
+ The devicePixelContentBox size of each child element is observed
+ with a ResizeObserver and when changed, a pattern is applied to
+ the element and the pattern's size set so each pixel in the pattern
+ will be one device pixel.
+ A similar process happens in the test HTML using canvases
+ and patterns generated using putImageData.
+ The test and this reference page should then match.
+ */
+
+ const outerElem = document.querySelector('.outer');
+
+ let resolve;
+ const promise = new Promise(_resolve => (resolve = _resolve));
+
+ /**
+ * Set the pattern's size on this element so that it draws where
+ * 1 pixel in the pattern maps to 1 devicePixel.
+ */
+ function setPatterns(entries) {
+ for (const entry of entries) {
+ setPattern(entry.target)
+ }
+ resolve();
+ }
+
+ const observer = new ResizeObserver(setPatterns);
+ for (let percentSize = 7; percentSize < 100; percentSize += 13) {
+ const innerElem = document.createElement('div');
+ innerElem.style.width = `${percentSize}%`;
+ observer.observe(innerElem, {box:"device-pixel-content-box"});
+ outerElem.appendChild(innerElem);
+ }
+
+ await promise;
+ takeScreenshotDelayed(50);
+ })();
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.html.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.html.js
new file mode 100644
index 0000000000..0b4d35bdec
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.html.js
@@ -0,0 +1,147 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import createPatternDataURL from './create-pattern-data-url.js';
+import { runRefTest } from './gpu_ref_test.js';
+runRefTest(async t => {
+ const { patternSize, imageData: patternImageData } = createPatternDataURL();
+
+ document.querySelector('#dpr').textContent = `dpr: ${devicePixelRatio}`;
+
+ const device = t.device;
+ const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
+
+ const module = device.createShaderModule({
+ code: `
+ @vertex fn vs(
+ @builtin(vertex_index) VertexIndex : u32
+ ) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 3>(
+ vec2(-1.0, 3.0),
+ vec2(-1.0,-1.0),
+ vec2( 3.0,-1.0)
+ );
+
+ return vec4(pos[VertexIndex], 0.0, 1.0);
+ }
+
+ @group(0) @binding(0) var pattern: texture_2d<f32>;
+
+ @fragment fn fs(
+ @builtin(position) Pos : vec4<f32>
+ ) -> @location(0) vec4<f32> {
+ let patternSize = textureDimensions(pattern, 0);
+ let uPos = vec2u(Pos.xy) % patternSize;
+ return textureLoad(pattern, uPos, 0);
+ }
+ `,
+ });
+
+ const pipeline = device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module,
+ entryPoint: 'vs',
+ },
+ fragment: {
+ module,
+ entryPoint: 'fs',
+ targets: [{ format: presentationFormat }],
+ },
+ });
+
+ const tex = device.createTexture({
+ size: [patternSize, patternSize, 1],
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
+ });
+ device.queue.writeTexture(
+ { texture: tex },
+ patternImageData.data,
+ { bytesPerRow: patternSize * 4, rowsPerImage: 4 },
+ { width: patternSize, height: patternSize }
+ );
+
+ const bindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: tex.createView() }],
+ });
+
+ function setCanvasPattern(canvas, devicePixelWidth, devicePixelHeight) {
+ canvas.width = devicePixelWidth;
+ canvas.height = devicePixelHeight;
+
+ const context = canvas.getContext('webgpu');
+ context.configure({
+ device,
+ format: presentationFormat,
+ alphaMode: 'premultiplied',
+ });
+
+ const encoder = device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ view: context.getCurrentTexture().createView(),
+ clearValue: [0.0, 0.0, 0.0, 0.0],
+ loadOp: 'clear',
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.draw(3);
+ pass.end();
+
+ device.queue.submit([encoder.finish()]);
+ }
+
+ /*
+ This test creates elements like this
+ <body>
+ <div class="outer">
+ <canvas></canvas>
+ <canvas></canvas>
+ <canvas></canvas>
+ ...
+ </div>
+ </body>
+ Where the outer div is a flexbox centering the child canvases.
+ Each of the child canvases is set to a different width in percent.
+ The size of each canvas in device pixels is queried with ResizeObserver
+ and then each canvases' resolution is set to that size so that there should
+ be one pixel in each canvas for each device pixel.
+ Each canvas is filled with a pattern using putImageData.
+ In the reference the canvas elements are replaced with divs.
+ For the divs the same pattern is applied with CSS and its size
+ adjusted so the pattern should appear with one pixel in the pattern
+ corresponding to 1 device pixel.
+ The reference and this page should then match.
+ */
+
+ const outerElem = document.querySelector('.outer');
+
+ let resolve;
+ const promise = new Promise(_resolve => (resolve = _resolve));
+
+ function setPatternsUsingSizeInfo(entries) {
+ for (const entry of entries) {
+ setCanvasPattern(
+ entry.target,
+ entry.devicePixelContentBoxSize[0].inlineSize,
+ entry.devicePixelContentBoxSize[0].blockSize
+ );
+ }
+ resolve(true);
+ }
+
+ const observer = new ResizeObserver(setPatternsUsingSizeInfo);
+ for (let percentSize = 7; percentSize < 100; percentSize += 13) {
+ const canvasElem = document.createElement('canvas');
+ canvasElem.style.width = `${percentSize}%`;
+ observer.observe(canvasElem, { box: 'device-pixel-content-box' });
+ outerElem.appendChild(canvasElem);
+ }
+
+ await promise;
+});
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html
new file mode 100644
index 0000000000..2845cc29eb
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/reftests/resize_observer.https.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>WebGPU resize_observer</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU canvases should return the correct ResizeObserver values" />
+ <link rel="match" href="./ref/resize_observer-ref.html" />
+ <style>
+ .outer {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ }
+ .outer>* {
+ display: block;
+ height: 100px;
+ }
+ </style>
+ <body>
+ <div id="dpr"></div>
+ <div class="outer"></div>
+ <script type="module" src="resize_observer.html.js"></script>
+ </body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js
new file mode 100644
index 0000000000..76adb619a2
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/util.js
@@ -0,0 +1,170 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { SkipTestCase } from '../../common/framework/fixture.js';
+import {
+ assert,
+ ErrorWithExtra,
+ raceWithRejectOnTimeout,
+ unreachable,
+} from '../../common/util/util.js';
+
+/**
+ * Starts playing a video and waits for it to be consumable.
+ * Returns a promise which resolves after `callback` (which may be async) completes.
+ *
+ * @param video An HTML5 Video element.
+ * @param callback Function to call when video is ready.
+ *
+ * Adapted from https://github.com/KhronosGroup/WebGL/blob/main/sdk/tests/js/webgl-test-utils.js
+ */
+export function startPlayingAndWaitForVideo(video, callback) {
+ return raceWithRejectOnTimeout(
+ new Promise((resolve, reject) => {
+ const callbackAndResolve = () =>
+ void (async () => {
+ try {
+ await callback();
+ resolve();
+ } catch (ex) {
+ reject();
+ }
+ })();
+ if (video.error) {
+ reject(
+ new ErrorWithExtra('Video.error: ' + video.error.message, () => ({ error: video.error }))
+ );
+
+ return;
+ }
+
+ video.addEventListener(
+ 'error',
+ event => reject(new ErrorWithExtra('Video received "error" event', () => ({ event }))),
+ true
+ );
+
+ if ('requestVideoFrameCallback' in video) {
+ video.requestVideoFrameCallback(() => {
+ callbackAndResolve();
+ });
+ } else {
+ // If requestVideoFrameCallback isn't available, check each frame if the video has advanced.
+ const timeWatcher = () => {
+ if (video.currentTime > 0) {
+ callbackAndResolve();
+ } else {
+ requestAnimationFrame(timeWatcher);
+ }
+ };
+ timeWatcher();
+ }
+
+ video.loop = true;
+ video.muted = true;
+ video.preload = 'auto';
+ video.play().catch(reject);
+ }),
+ 2000,
+ 'Video never became ready'
+ );
+}
+
+/**
+ * Fire a `callback` when the video reaches a new frame.
+ * Returns a promise which resolves after `callback` (which may be async) completes.
+ *
+ * MAINTENANCE_TODO: Find a way to implement this for browsers without requestVideoFrameCallback as
+ * well, similar to the timeWatcher path in startPlayingAndWaitForVideo. If that path is proven to
+ * work well, we can consider getting rid of the requestVideoFrameCallback path.
+ */
+export function waitForNextFrame(video, callback) {
+ const { promise, callbackAndResolve } = videoCallbackHelper(
+ callback,
+ 'waitForNextFrame timed out'
+ );
+
+ if ('requestVideoFrameCallback' in video) {
+ video.requestVideoFrameCallback(() => {
+ callbackAndResolve();
+ });
+ } else {
+ throw new SkipTestCase('waitForNextFrame currently requires requestVideoFrameCallback');
+ }
+
+ return promise;
+}
+
+export function getVideoColorSpaceInit(colorSpaceName) {
+ switch (colorSpaceName) {
+ case 'REC601':
+ return {
+ primaries: 'smpte170m',
+ transfer: 'smpte170m',
+ matrix: 'smpte170m',
+ fullRange: false,
+ };
+ case 'REC709':
+ return { primaries: 'bt709', transfer: 'bt709', matrix: 'bt709', fullRange: false };
+ case 'REC2020':
+ return { primaries: 'bt709', transfer: 'iec61966-2-1', matrix: 'rgb', fullRange: true };
+ default:
+ unreachable();
+ }
+}
+
+export async function getVideoFrameFromVideoElement(
+ test,
+ video,
+ colorSpace = getVideoColorSpaceInit('REC709')
+) {
+ if (video.captureStream === undefined) {
+ test.skip('HTMLVideoElement.captureStream is not supported');
+ }
+
+ const track = video.captureStream().getVideoTracks()[0];
+ const reader = new MediaStreamTrackProcessor({ track }).readable.getReader();
+ const videoFrame = (await reader.read()).value;
+ assert(videoFrame !== undefined, 'unable to get a VideoFrame from track 0');
+ assert(
+ videoFrame.format !== null && videoFrame.timestamp !== null,
+ 'unable to get a valid VideoFrame from track 0'
+ );
+
+ // Apply color space info because the VideoFrame generated from captured stream
+ // doesn't have it.
+ const bufferSize = videoFrame.allocationSize();
+ const buffer = new ArrayBuffer(bufferSize);
+ const frameLayout = await videoFrame.copyTo(buffer);
+ const frameInit = {
+ format: videoFrame.format,
+ timestamp: videoFrame.timestamp,
+ codedWidth: videoFrame.codedWidth,
+ codedHeight: videoFrame.codedHeight,
+ colorSpace,
+ layout: frameLayout,
+ };
+ return new VideoFrame(buffer, frameInit);
+}
+
+/**
+ * Helper for doing something inside of a (possibly async) callback (directly, not in a following
+ * microtask), and returning a promise when the callback is done.
+ * MAINTENANCE_TODO: Use this in startPlayingAndWaitForVideo (and make sure it works).
+ */
+function videoCallbackHelper(callback, timeoutMessage) {
+ let callbackAndResolve;
+
+ const promiseWithoutTimeout = new Promise((resolve, reject) => {
+ callbackAndResolve = () =>
+ void (async () => {
+ try {
+ await callback(); // catches both exceptions and rejections
+ resolve();
+ } catch (ex) {
+ reject(ex);
+ }
+ })();
+ });
+ const promise = raceWithRejectOnTimeout(promiseWithoutTimeout, 2000, timeoutMessage);
+ return { promise, callbackAndResolve: callbackAndResolve };
+}
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js
new file mode 100644
index 0000000000..bda65f7cb0
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.js
@@ -0,0 +1,80 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ import { getGPU } from '../../../common/util/navigator_gpu.js';
+import { assert, objectEquals, iterRange } from '../../../common/util/util.js';
+async function basicTest() {
+ const adapter = await getGPU().requestAdapter();
+ assert(adapter !== null, 'Failed to get adapter.');
+
+ const device = await adapter.requestDevice();
+ assert(device !== null, 'Failed to get device.');
+
+ const kOffset = 1230000;
+ const pipeline = device.createComputePipeline({
+ layout: 'auto',
+ compute: {
+ module: device.createShaderModule({
+ code: `
+ struct Buffer { data: array<u32>, };
+
+ @group(0) @binding(0) var<storage, read_write> buffer: Buffer;
+ @compute @workgroup_size(1u) fn main(
+ @builtin(global_invocation_id) id: vec3<u32>) {
+ buffer.data[id.x] = id.x + ${kOffset}u;
+ }
+ `,
+ }),
+ entryPoint: 'main',
+ },
+ });
+
+ const kNumElements = 64;
+ const kBufferSize = kNumElements * 4;
+ const buffer = device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ const resultBuffer = device.createBuffer({
+ size: kBufferSize,
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
+ });
+
+ const bindGroup = device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: [{ binding: 0, resource: { buffer } }],
+ });
+
+ const encoder = device.createCommandEncoder();
+
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatchWorkgroups(kNumElements);
+ pass.end();
+
+ encoder.copyBufferToBuffer(buffer, 0, resultBuffer, 0, kBufferSize);
+
+ device.queue.submit([encoder.finish()]);
+
+ const expected = new Uint32Array([...iterRange(kNumElements, x => x + kOffset)]);
+
+ await resultBuffer.mapAsync(GPUMapMode.READ);
+ const actual = new Uint32Array(resultBuffer.getMappedRange());
+
+ assert(objectEquals(actual, expected), 'compute pipeline ran');
+
+ resultBuffer.destroy();
+ buffer.destroy();
+ device.destroy();
+}
+
+self.onmessage = async ev => {
+ let error = undefined;
+ try {
+ await basicTest();
+ } catch (err) {
+ error = err.toString();
+ }
+ self.postMessage({ error });
+};
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js
new file mode 100644
index 0000000000..4974414852
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker.spec.js
@@ -0,0 +1,36 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/ export const description = `
+Tests WebGPU is available in a worker.
+
+Note: The CTS test can be run in a worker by passing in worker=1 as
+a query parameter. This test is specifically to check that WebGPU
+is available in a worker.
+`;
+import { Fixture } from '../../../common/framework/fixture.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/util/util.js';
+
+export const g = makeTestGroup(Fixture);
+
+function isNode() {
+ return typeof process !== 'undefined' && process?.versions?.node !== undefined;
+}
+
+g.test('worker')
+ .desc(`test WebGPU is available in DedicatedWorkers and check for basic functionality`)
+ .fn(async t => {
+ if (isNode()) {
+ t.skip('node does not support 100% compatible workers');
+ return;
+ }
+ // Note: we load worker_launcher dynamically because ts-node support
+ // is using commonjs which doesn't support import.meta. Further,
+ // we need to put the url in a string add pass the string to import
+ // otherwise typescript tries to parse the file which again, fails.
+ // worker_launcher.js is excluded in node.tsconfig.json.
+ const url = './worker_launcher.js';
+ const { launchWorker } = await import(url);
+ const result = await launchWorker();
+ assert(result.error === undefined, `should be no error from worker but was: ${result.error}`);
+ });
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js
new file mode 100644
index 0000000000..d5bd412fb6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/worker/worker_launcher.js
@@ -0,0 +1,16 @@
+/**
+ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+ **/
+
+export async function launchWorker() {
+ const selfPath = import.meta.url;
+ const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
+ const workerPath = selfPathDir + '/worker.js';
+ const worker = new Worker(workerPath, { type: 'module' });
+
+ const promise = new Promise(resolve => {
+ worker.addEventListener('message', ev => resolve(ev.data), { once: true });
+ });
+ worker.postMessage({});
+ return await promise;
+}
diff --git a/testing/web-platform/mozilla/tests/websockets/bug1793935.any.js b/testing/web-platform/mozilla/tests/websockets/bug1793935.any.js
new file mode 100644
index 0000000000..4ef84b3da4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/websockets/bug1793935.any.js
@@ -0,0 +1,23 @@
+// The module has an import that's immediately called by the start function.
+const module = new Uint8Array([
+ 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96,
+ 0, 0, 2, 7, 1, 1, 97, 1, 98, 0, 0, 3,
+ 2, 1, 0, 8, 1, 1, 10, 6, 1, 4, 0, 16,
+ 0, 11, 0, 36, 16, 115, 111, 117, 114, 99, 101, 77,
+ 97, 112, 112, 105, 110, 103, 85, 82, 76, 18, 46, 47,
+ 114, 101, 108, 101, 97, 115, 101, 46, 119, 97, 115, 109,
+ 46, 109, 97, 112
+]);
+
+// The WebSocket server does not need to exist, because the bug occurs before
+// any connection is attempted.
+const imports = {
+ a: {
+ b: Reflect.construct.bind(null, WebSocket, ["ws://localhost:1234"])
+ }
+};
+
+promise_test(
+ () => WebAssembly.instantiate(module, imports),
+ "Ensure WebSockets can be constructed from WebAssembly"
+); \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/closed.tentative.https.html b/testing/web-platform/mozilla/tests/webtransport/bfcache/closed.tentative.https.html
new file mode 100644
index 0000000000..8fbf27922d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/closed.tentative.https.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>WebTransport API: bfcache closed</title>
+<link rel=help href="https://w3c.github.io/webtransport/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script type="module">
+
+import { runWebTransportBfcacheTest } from "./helpers.js";
+import { webtransport_url } from "./ports.sub.js";
+import { worker_function } from "./worker.js";
+
+const id = token();
+const url = webtransport_url(`client-close.py?token=${id}`);
+
+// We can't load ./worker.js in runWebTransportBfcacheTest, because it uses
+// execute_script, and so the baseurl is helper.sub.js's baseurl.
+// We also can't pass a worker to it. So, load the worker as a string, and pass
+// the string and turn it into a worker via a Blob. Fun!
+const worker_string = worker_function.toString().replace(/^async function .+\{?|\}$/g, '');
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (url) => {
+ window.wt = new WebTransport(url);
+ await window.wt.ready;
+ window.wt.close();
+ await window.wt.closed;
+ },
+ argsBeforeNavigation: [url],
+ shouldBeCached: true
+}, "A closed WebTransport on MainThread must allow bfcache");
+
+// we can't have runWebTransportBfcacheTest use [scripts] to load the helper.js
+// script into the test, due to the same baseurl issue, so just do this inline
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new SharedWorker(URL.createObjectURL(workerBlob));
+ worker.port.start();
+ await postToWorkerAndWait(worker.port, { op: "openandclose", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A closed WebTransport in a shared worker must allow bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ await postToWorkerAndWait(window.worker, { op: "close" });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A closed WebTransport in a worker must allow bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ await postToWorkerAndWait(window.worker, { op: "close" });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A closed WebTransport in a nested worker must allow bfcache");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/connected.tentative.https.html b/testing/web-platform/mozilla/tests/webtransport/bfcache/connected.tentative.https.html
new file mode 100644
index 0000000000..de2a2fc7a7
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/connected.tentative.https.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>WebTransport API: bfcache connected</title>
+<link rel=help href="https://w3c.github.io/webtransport/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script type="module">
+
+import { runWebTransportBfcacheTest } from "./helpers.js";
+import { webtransport_url } from "./ports.sub.js";
+import { worker_function } from "./worker.js";
+
+const id = token();
+const url = webtransport_url(`client-close.py?token=${id}`);
+
+// We can't load ./worker.js in runWebTransportBfcacheTest, because it uses
+// execute_script, and so the baseurl is helper.sub.js's baseurl, which is
+// the main wpt test directory.
+// We also can't pass a worker to it. So, load the worker as a string, and pass
+// the string and turn it into a worker via a Blob. Fun!
+const worker_string = worker_function.toString().replace(/^async function .+\{?|\}$/g, '');
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (url) => {
+ window.wt = new WebTransport(url);
+ await window.wt.ready;
+ },
+ argsBeforeNavigation: [url],
+ shouldBeCached: false
+}, "A connected WebTransport on MainThread must prevent bfcache");
+
+// we can't have runWebTransportBfcacheTest use [scripts] to load the helper.js
+// script into the test, due to the same baseurl issue, so just do this inline
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new SharedWorker(URL.createObjectURL(workerBlob));
+ worker.port.start();
+ await postToWorkerAndWait(worker.port, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: false
+}, "A connected WebTransport in a shared worker must prevent bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: false
+}, "A connected WebTransport in a worker must prevent bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: false
+}, "A connected WebTransport in a nested worker must prevent bfcache");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/failed.tentative.https.html b/testing/web-platform/mozilla/tests/webtransport/bfcache/failed.tentative.https.html
new file mode 100644
index 0000000000..94facfa6a8
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/failed.tentative.https.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>WebTransport API: bfcache failed</title>
+<link rel=help href="https://w3c.github.io/webtransport/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script type="module">
+
+import { runWebTransportBfcacheTest } from "./helpers.js";
+import { webtransport_url } from "./ports.sub.js";
+import { worker_function } from "./worker.js";
+
+const id = token();
+const url = webtransport_url('custom-response.py?:status=404');
+
+// We can't load ./worker.js in runWebTransportBfcacheTest, because it uses
+// execute_script, and so the baseurl is helper.sub.js's baseurl.
+// We also can't pass a worker to it. So, load the worker as a string, and pass
+// the string and turn it into a worker via a Blob. Fun!
+const worker_string = worker_function.toString().replace(/^async function .+\{?|\}$/g, '');
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (url) => {
+ // make sure it isn't immediately freed
+ try {
+ window.wt = new WebTransport(url);
+ await window.wt.ready;
+ assert_unreached('Opened invalid URL');
+ } catch(e) {
+ }
+ },
+ argsBeforeNavigation: [url],
+ shouldBeCached: true
+}, "A failed WebTransport on MainThread must allow bfcache");
+
+// we can't have runWebTransportBfcacheTest use [scripts] to load the helper.js
+// script into the test, due to the same baseurl issue, so just do this inline
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new SharedWorker(URL.createObjectURL(workerBlob));
+ worker.port.start();
+ await postToWorkerAndWait(worker.port, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A failed WebTransport in a shared worker must allow bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A failed WebTransport in a worker must allow bfcache");
+
+runWebTransportBfcacheTest({
+ funcBeforeNavigation: async (worker_string, url) => {
+ let next_request_id = 0;
+ function postToWorkerAndWait(worker, data) {
+ return new Promise(resolve => {
+ data.rqid = next_request_id++;
+ worker.postMessage(data);
+ const listener = event => {
+ if (event.data.rqid !== data.rqid)
+ return;
+ worker.removeEventListener('message', listener);
+ resolve(event.data);
+ };
+ worker.addEventListener('message', listener);
+ });
+ };
+
+ let workerBlob = new Blob([worker_string], { type:'text/javascript' });
+ window.worker = new Worker(URL.createObjectURL(workerBlob));
+ await postToWorkerAndWait(window.worker, { op: "open", url: url });
+ },
+ argsBeforeNavigation: [worker_string, url],
+ shouldBeCached: true
+}, "A failed WebTransport in a nested worker must allow bfcache");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/helpers.js b/testing/web-platform/mozilla/tests/webtransport/bfcache/helpers.js
new file mode 100644
index 0000000000..d8ab9b62d3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/helpers.js
@@ -0,0 +1,17 @@
+export function runWebTransportBfcacheTest(params, description) {
+ runBfcacheTest(
+ {
+ // due to the baseurl issue, this would try to load the scripts from
+ // the main wpt test directory
+ // scripts: ["/webtransport/resources/helpers.js"],
+ openFunc: url =>
+ window.open(
+ url + `&prefix=${location.pathname}-${description}`,
+ "_blank",
+ "noopener"
+ ),
+ ...params,
+ },
+ description
+ );
+}
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/ports.sub.js b/testing/web-platform/mozilla/tests/webtransport/bfcache/ports.sub.js
new file mode 100644
index 0000000000..cb4262c9f4
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/ports.sub.js
@@ -0,0 +1,12 @@
+// The file including this must also include /common/get-host-info.sub.js to
+// pick up the necessary constants.
+
+const HOST = get_host_info().ORIGINAL_HOST;
+const PORT = '{{ports[webtransport-h3][0]}}';
+const BASE = `https://${HOST}:${PORT}`;
+
+// Create URL for WebTransport session.
+export function webtransport_url(handler) {
+ return `${BASE}/webtransport/handlers/${handler}`;
+}
+
diff --git a/testing/web-platform/mozilla/tests/webtransport/bfcache/worker.js b/testing/web-platform/mozilla/tests/webtransport/bfcache/worker.js
new file mode 100644
index 0000000000..b0eb890f42
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webtransport/bfcache/worker.js
@@ -0,0 +1,50 @@
+export async function worker_function() {
+
+let wt = null;
+
+async function processMessage(e) {
+ const target = this;
+
+ function respond(data) {
+ target.postMessage(Object.assign(data, {rqid: e.data.rqid}));
+ }
+
+ // ORB will block errors (webtransport_url('custom-response.py?:status=404');)
+ // so we need to try/catch
+ try {
+ switch (e.data.op) {
+ case 'open': {
+ wt = new WebTransport(e.data.url);
+ await wt.ready;
+ respond({ack: 'open'});
+ break;
+ }
+
+ case 'openandclose': {
+ wt = new WebTransport(e.data.url);
+ await wt.ready;
+ wt.close();
+ await wt.closed;
+ respond({ack: 'openandclose'});
+ break;
+ }
+
+ case 'close': {
+ wt.close();
+ await wt.closed;
+ respond({ack: 'close'});
+ break;
+ }
+ }
+ } catch(e) {
+ respond({failed: true});
+ }
+}
+
+self.addEventListener('message', processMessage);
+
+self.addEventListener('connect', ev => {
+ // Shared worker case
+ ev.ports[0].onmessage = processMessage;
+});
+}
diff --git a/testing/web-platform/mozilla/tests/workers/2-mib-file.py b/testing/web-platform/mozilla/tests/workers/2-mib-file.py
new file mode 100644
index 0000000000..cfb563ff21
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/2-mib-file.py
@@ -0,0 +1,7 @@
+import random
+import string
+
+
+def main(request, response):
+ r = "".join(random.choice(string.ascii_letters) for _ in range(2 * 1024 * 1024))
+ return r
diff --git a/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html b/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html
new file mode 100644
index 0000000000..2b037e5b37
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/bug1674278-crash.html
@@ -0,0 +1,6 @@
+<html class='test-wait'>
+<script>
+var worker = new Worker('bug1674278.js');
+worker.postMessage('', []);
+</script>
+</html>
diff --git a/testing/web-platform/mozilla/tests/workers/bug1674278.js b/testing/web-platform/mozilla/tests/workers/bug1674278.js
new file mode 100644
index 0000000000..56105cb76e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/bug1674278.js
@@ -0,0 +1,6 @@
+self.onmessage = async function(e) {
+ var a = await self.fetch('2-mib-file.py');
+ var b = await a.blob();
+ self.close()
+ await b.arrayBuffer();
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html b/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html
new file mode 100644
index 0000000000..ed38ecb3e5
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/dedicated-worker-import-csp.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: CSP for ES Modules</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async function openWindow(url) {
+ const win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_equals(msg_event.data, 'LOADED');
+ return win;
+}
+
+function import_csp_test(
+ cspHeader, importType, expectedImportedModules, description) {
+ // Append CSP header to windowURL for static import tests since static import
+ // scripts should obey Window's CSP.
+ const windowURL = `resources/new-worker-window.html`;
+ // Append CSP header to scriptURL for dynamic import tests since dynamic
+ // import scripts should obey Worker script's response's CSP.
+ const scriptURL = `${importType}-import-remote-origin-script-worker.sub.js` +
+ `?pipe=header(Content-Security-Policy, ${cspHeader})`;
+ promise_test(async () => {
+ const win = await openWindow(windowURL);
+ // Ask the window to start a dedicated worker.
+ win.postMessage(scriptURL, '*');
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_array_equals(msg_event.data, expectedImportedModules);
+ }, description);
+}
+
+// Tests for static import.
+//
+// Static import should obey the worker-src directive and the script-src
+// directive. If the both directives are specified, the worker-src directive
+// should be prioritized.
+//
+// Step 1: "If the result of executing 6.6.1.11 Get the effective directive for
+// request on request is "worker-src", and policy contains a directive whose
+// name is "worker-src", return "Allowed"."
+// "Note: If worker-src is present, we’ll defer to it when handling worker
+// requests."
+// https://w3c.github.io/webappsec-csp/#script-src-pre-request
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "worker-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "worker-src * 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should allow cross origin static import.")
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin static import.")
+
+import_csp_test(
+ "worker-src *; script-src 'self' 'unsafe-inline'",
+ "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should override script-src 'self' directive and " +
+ "allow cross origin static import.");
+
+import_csp_test(
+ "worker-src 'self'; script-src * 'unsafe-inline'",
+ "static",
+ ['ERROR'],
+ "worker-src 'self' directive should override script-src * directive and " +
+ "disallow cross origin static import.");
+
+// Tests for dynamic import.
+//
+// Dynamic import should obey the script-src directive instead of the worker-src
+// directive according to the specs:
+//
+// Dynamic import has the "script" destination.
+// Step 2.4: "Fetch a module script graph given url, ..., "script", ..."
+// https://html.spec.whatwg.org/multipage/webappapis.html#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)
+//
+// The "script" destination should obey the script-src CSP directive.
+// Step 2: "If request's destination is script-like:"
+// https://w3c.github.io/webappsec-csp/#script-src-pre-request
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'",
+ "dynamic",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin dynamic import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'",
+ "dynamic",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin dynamic import.")
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'",
+ "dynamic",
+ ["export-on-load-script.js"],
+ "worker-src 'self' directive should not take effect on dynamic import.");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js b/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js
new file mode 100644
index 0000000000..7ed6543890
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/dynamic-import-remote-origin-script-worker.sub.js
@@ -0,0 +1,17 @@
+// Import a remote origin script.
+const importUrl =
+ 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.js';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ import(importUrl)
+ .then(module => postMessage(module.importedModules))
+ .catch(e => postMessage(['ERROR']));
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ import(importUrl)
+ .then(module => e.ports[0].postMessage(module.importedModules))
+ .catch(error => e.ports[0].postMessage(['ERROR']));
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html b/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html
new file mode 100644
index 0000000000..84564fd7b6
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/new-shared-worker-window.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>SharedWorker: new SharedWorker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+let worker;
+
+// Create a new shared worker for a given script url.
+window.onmessage = e => {
+ worker = new SharedWorker(e.data.scriptURL,
+ { name: e.data.name, type: 'module' });
+ worker.port.onmessage = msg => window.opener.postMessage(msg.data, '*');
+ worker.onerror = err => {
+ window.opener.postMessage(['ERROR'], '*');
+ err.preventDefault();
+ };
+}
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html b/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html
new file mode 100644
index 0000000000..32a89fae0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/new-worker-window.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: new Worker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+let worker;
+
+// Creates a new dedicated worker for a given script url.
+window.onmessage = e => {
+ worker = new Worker(e.data, { type: 'module' });
+ worker.postMessage('start');
+ worker.onmessage = msg => window.opener.postMessage(msg.data, '*');
+ worker.onerror = err => {
+ window.opener.postMessage(['ERROR'], '*');
+ err.preventDefault();
+ };
+};
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js b/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js
new file mode 100644
index 0000000000..6432dd5d80
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/resources/static-import-remote-origin-script-worker.sub.js
@@ -0,0 +1,20 @@
+// Import a remote origin script.
+import * as module from 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ self.onmessage = e => {
+ e.target.postMessage(module.importedModules);
+ };
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ self.onconnect = e => {
+ e.ports[0].postMessage(module.importedModules);
+ };
+} else if (
+ 'ServiceWorkerGlobalScope' in self &&
+ self instanceof ServiceWorkerGlobalScope) {
+ self.onmessage = e => {
+ e.source.postMessage(module.importedModules);
+ };
+}
diff --git a/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html b/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html
new file mode 100644
index 0000000000..707b6fb020
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/modules/shared-worker-import-csp.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<title>SharedWorker: CSP for ES Modules</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// This Set is for checking a shared worker in each test is newly created.
+const existingWorkers = new Set();
+
+async function openWindow(url) {
+ const win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ const msgEvent = await new Promise(resolve => window.onmessage = resolve);
+ assert_equals(msgEvent.data, 'LOADED');
+ return win;
+}
+
+function import_csp_test(
+ cspHeader, importType, expectedImportedModules, description) {
+ // Append CSP header to windowURL for static import tests since static import
+ // scripts should obey Window's CSP.
+ const windowURL = "resources/new-shared-worker-window.html"
+ // Append CSP header to scriptURL as scripts should obey SharedWorker
+ // script's responce's CSP.
+ const scriptURL = `${importType}-import-remote-origin-script-worker.sub.js` +
+ `?pipe=header(Content-Security-Policy, ${cspHeader})`;
+ promise_test(async () => {
+ // Open a window that has the given CSP header.
+ const win = await openWindow(windowURL);
+ // Construct a unique name for SharedWorker.
+ const name = `${cspHeader}_${importType}`;
+ const workerProperties = { scriptURL, name };
+ // Check if this shared worker is newly created.
+ assert_false(existingWorkers.has(workerProperties));
+ existingWorkers.add(workerProperties);
+
+ // Ask the window to start a shared worker with the given CSP header.
+ // The shared worker doesn't inherits the window's CSP header.
+ // https://w3c.github.io/webappsec-csp/#initialize-global-object-csp
+ win.postMessage(workerProperties, '*');
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_array_equals(msg_event.data, expectedImportedModules);
+ }, description);
+}
+
+// Tests for static import.
+//
+// Static import should obey the worker-src directive and the script-src
+// directive. If the both directives are specified, the worker-src directive
+// should be prioritized.
+//
+// "The script-src directive acts as a default fallback for all script-like
+// destinations (including worker-specific destinations if worker-src is not
+// present)."
+// https://w3c.github.io/webappsec-csp/#directive-script-src
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'", "static",
+ ['ERROR'],
+ "worker-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "worker-src * 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should allow cross origin static import.");
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'", "static",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin static import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin static import.");
+
+import_csp_test(
+ "worker-src *; script-src 'self' 'unsafe-inline'", "static",
+ ["export-on-load-script.js"],
+ "worker-src * directive should override script-src 'self' directive and " +
+ "allow cross origin static import.");
+
+import_csp_test(
+ "worker-src 'self'; script-src * 'unsafe-inline'", "static",
+ ['ERROR'],
+ "worker-src 'self' directive should override script-src * directive and " +
+ "disallow cross origin static import.");
+
+// Tests for dynamic import.
+//
+// Dynamic import should obey SharedWorker script's CSP instead of parent
+// Window's CSP.
+//
+// Dynamic import should obey the script-src directive instead of the worker-src
+// directive according to the specs:
+//
+// Dynamic import has the "script" destination.
+// Step 3: "Fetch a single module script graph given url, ..., "script", ..."
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-an-import()-module-script-graph
+//
+// The "script" destination should obey the script-src CSP directive.
+// "The script-src directive acts as a default fallback for all script-like
+// destinations (including worker-specific destinations if worker-src is not
+// present)."
+// https://w3c.github.io/webappsec-csp/#directive-script-src
+
+import_csp_test(
+ "script-src 'self' 'unsafe-inline'", "dynamic",
+ ['ERROR'],
+ "script-src 'self' directive should disallow cross origin dynamic import.");
+
+import_csp_test(
+ "script-src * 'unsafe-inline'", "dynamic",
+ ["export-on-load-script.js"],
+ "script-src * directive should allow cross origin dynamic import.");
+
+import_csp_test(
+ "worker-src 'self' 'unsafe-inline'", "dynamic",
+ ["export-on-load-script.js"],
+ "worker-src 'self' directive should not take effect on dynamic import.");
+
+</script>
diff --git a/testing/web-platform/mozilla/tests/workers/resources/worker.js b/testing/web-platform/mozilla/tests/workers/resources/worker.js
new file mode 100644
index 0000000000..cc1692eb9c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/resources/worker.js
@@ -0,0 +1,129 @@
+const maxNestingLevel = 5;
+let expectedNestingLevel = 1;
+let timer;
+let isInterval = false;
+let testStage = "ScriptLoaded";
+let stopIncreaseExpectedLevel = false;
+let startClampedTimeStamp = 0;
+let startRepeatingClamped = false;
+let repeatCount = 0;
+let maxRepeatTimes = 10;
+
+let timerCallback = async () => {
+ let now = Date.now();
+ if (WorkerTestUtils.currentTimerNestingLevel() !== expectedNestingLevel) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level is ${WorkerTestUtils.currentTimerNestingLevel()}, expected ${expectedNestingLevel}`,
+ });
+ if (isInterval) {
+ clearInterval(timer);
+ }
+ return;
+ }
+
+ if (!stopIncreaseExpectedLevel) {
+ if (expectedNestingLevel === maxNestingLevel) {
+ stopIncreaseExpectedLevel = true;
+ startClampedTimeStamp = now;
+ } else {
+ expectedNestingLevel = expectedNestingLevel + 1;
+ }
+ if (!isInterval) {
+ setTimeout(timerCallback, 0);
+ }
+ return;
+ }
+
+ // This is the first time the timeout is clamped, checking if it is clamped
+ // to at least 2ms.
+ if (repeatCount === 0) {
+ await Promise.resolve(true).then(() => {
+ if (WorkerTestUtils.currentTimerNestingLevel() !== expectedNestingLevel) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `Timer nesting level should be in effect for immediately resolved micro-tasks`,
+ });
+ }
+ });
+ if (now - startClampedTimeStamp < 2 ) {
+ startRepeatingClamped = true;
+ } else {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ }
+ }
+
+ // If the first clamped timeout is less than 2ms, start to repeat the clamped
+ // timeout for 10 times. Then checking if total clamped time should be at least
+ // 25ms.
+ if (startRepeatingClamped) {
+ if (repeatCount === 10) {
+ if (now - startClampedTimeStamp < 25) {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `total clamped time of repeating ten times should be at least 25ms(${now - startClampedTimeStamp})`,
+ });
+ } else {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ }
+ } else {
+ repeatCount = repeatCount + 1;
+ if (!isInterval) {
+ setTimeout(timerCallback, 0);
+ }
+ return;
+ }
+ }
+
+ // reset testing variables
+ repeatCount = 0;
+ startRepeatingClamped = false;
+ stopIncreaseExpectedLevel = false;
+ if (isInterval) {
+ clearInterval(timer);
+ }
+};
+
+onmessage = async e => {
+ testStage = e.data;
+ switch (e.data) {
+ case "CheckInitialValue":
+ if (WorkerTestUtils.currentTimerNestingLevel() === 0) {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ } else {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level should be 0(${WorkerTestUtils.currentTimerNestingLevel()}) after top level script loaded.`,
+ });
+ }
+ break;
+ case "TestSetInterval":
+ expectedNestingLevel = 1;
+ isInterval = true;
+ timer = setInterval(timerCallback, 0);
+ break;
+ case "TestSetTimeout":
+ expectedNestingLevel = 1;
+ isInterval = false;
+ setTimeout(timerCallback, 0);
+ break;
+ case "CheckNoTimer":
+ if (WorkerTestUtils.currentTimerNestingLevel() === 0) {
+ postMessage({ stage: testStage, status: "PASS", msg: "" });
+ } else {
+ postMessage({
+ stage: testStage,
+ status: "FAIL",
+ msg: `current timer nesting level should be 0(${WorkerTestUtils.currentTimerNestingLevel()}) when there is no timer in queue.`,
+ });
+ }
+
+ break;
+ }
+};
+
+postMessage({ stage: testStage, status: "PASS" });
diff --git a/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html b/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html
new file mode 100644
index 0000000000..e39f9e1b0e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/workers/worker_timer_nesting_level.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Worker: Timer Nesting Level</title>
+<Script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict'
+
+/**
+ * This test includes following four test stages.
+ * 1. CheckInitialValue: Checking the initial value of worker's current timer
+ * nesting level after the worker's top level script is loaded. The result
+ * is expected as 0.
+ * 2. TestSetInterval: Checking the worker's current timer nesting level with
+ * setInterval with following steps
+ * 1. call setInterval(callback, 0) to create a repeating timer.
+ * 2. checking the current timer nesting level in the callback. The value
+ * should increase every time executing the callback until it reaches the
+ * maximun nesting level(5).
+ * 3. Checking the worker's current timer nesting level with immediately
+ * resolved promise.
+ * 4. Checking the the time duration between two callback launching.
+ * 3. TestSetTimeout: Checking the worker's current timer nesting level with
+ * setTimeout. This stage has similar test steps with TestSetInterval.
+ * The difference is this stage using the recursive setTimeout to accumulate
+ * the timer nesting level.
+ * 4. CheckNoTimer: Checking the situation which the worker has no pending
+ * timer. The result is expected as 0.
+ */
+
+let testStages = ["CheckInitialValue",
+ "TestSetInterval",
+ "TestSetTimeout",
+ "CheckNoTimer"];
+
+promise_test(async function(t) {
+ let result = await new Promise( (resolve, reject) => {
+ let worker = new Worker("resources/worker.js");
+ worker.onmessage = (e) => {
+ if (e.data.status === "FAIL") {
+ resolve(e.data);
+ return;
+ }
+ if (testStages.length !== 0) {
+ worker.postMessage(testStages.shift());
+ } else {
+ resolve({status: "PASS", msg: "Timer nesting level for workers"});
+ }
+ };
+ });
+ assert_true(result.status === "PASS", result.msg);
+}, 'Worker timer nesting level');
+</script>
diff --git a/testing/web-platform/mozilla/tests/xml/parsedepth.html b/testing/web-platform/mozilla/tests/xml/parsedepth.html
new file mode 100644
index 0000000000..b0b17fe98e
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/xml/parsedepth.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+
+function parseBlob(blob) {
+ return new Promise(resolve => {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", URL.createObjectURL(blob));
+ xhr.onload = () => {
+ resolve(xhr.responseXML);
+ }
+ xhr.send();
+ });
+}
+
+promise_test(async (t) => {
+ // Most browser engines, including Gecko, use 5000 as the limit, so test a
+ // range around that.
+ const cutoff = 5000;
+
+ let minDepth = cutoff - 100;
+ let maxDepth = cutoff + 100;
+
+ // Generate a string with elements nested maxDepth deep.
+ const openTag = "<x>";
+ const closeTag = "</x>";
+ let xml = openTag.repeat(maxDepth) + closeTag.repeat(maxDepth);
+
+ // Compute where we change from opening to closing tags.
+ const middle = maxDepth * openTag.length;
+
+ // Create a blob around the string.
+ let blob = new Blob([xml], { type: "application/xml" });
+
+ while (minDepth < maxDepth) {
+ // Try to parse a number of nested tags between minDepth and maxDepth.
+ let test = Math.ceil((minDepth + maxDepth) / 2);
+
+ // We need the number of opening and closing tags to be equal to the number
+ // that we calculated above.
+ let slice = blob.slice(middle - (test * openTag.length),
+ middle + (test * closeTag.length));
+
+ let responseXML = await parseBlob(slice);
+
+ // Move either minDepth or maxDepth so that the actual limit is still in the
+ // range of [minDepth-maxDepth].
+ if (responseXML) {
+ // Depth is ok.
+ minDepth = test;
+ } else {
+ maxDepth = test - 1;
+ }
+ }
+ assert_equals(minDepth, maxDepth);
+ assert_equals(minDepth, cutoff);
+},"Parsing XML fails when the nesting depth is 5000");
+
+</script>